| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- /*
- * decaffeinate suggestions:
- * DS101: Remove unnecessary use of Array.from
- * DS102: Remove unnecessary code created because of implicit returns
- * DS205: Consider reworking code to avoid use of IIFEs
- * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
- */
- const prom = require('prom-client');
- const registry = require('prom-client').register;
- const metrics = new Map();
- const optsKey = function(opts) {
- let keys = Object.keys(opts);
- if (keys.length === 0) { return ''; }
- keys = keys.sort();
- let hash = '';
- for (let key of Array.from(keys)) {
- if (hash.length) { hash += ","; }
- hash += `${key}:${opts[key]}`;
- }
- return hash;
- };
- const extendOpts = function(opts, labelNames) {
- for (let label of Array.from(labelNames)) {
- if (!opts[label]) { opts[label] = ''; }
- }
- return opts;
- };
- const optsAsArgs = function(opts, labelNames) {
- const args = [];
- for (let label of Array.from(labelNames)) {
- args.push(opts[label] || '');
- }
- return args;
- };
- const PromWrapper = {
- ttlInMinutes: 0,
- registry,
- metric(type, name) {
- return metrics.get(name) || new MetricWrapper(type, name);
- },
- collectDefaultMetrics: prom.collectDefaultMetrics
- };
- class MetricWrapper {
- constructor(type, name) {
- metrics.set(name, this);
- this.name = name;
- this.instances = new Map();
- this.lastAccess = new Date();
- this.metric = (() => { switch (type) {
- case "counter":
- return new prom.Counter({
- name,
- help: name,
- labelNames: ['app','host','status','method', 'path']
- });
- case "summary":
- return new prom.Summary({
- name,
- help: name,
- maxAgeSeconds: 60,
- ageBuckets: 10,
- labelNames: ['app', 'host', 'path', 'status_code', 'method', 'collection', 'query']
- });
- case "gauge":
- return new prom.Gauge({
- name,
- help: name,
- labelNames: ['app','host', 'status']
- });
- } })();
- }
- inc(opts, value) {
- return this._execMethod('inc', opts, value);
- }
- observe(opts, value) {
- return this._execMethod('observe', opts, value);
- }
- set(opts, value) {
- return this._execMethod('set', opts, value);
- }
- sweep() {
- const thresh = new Date(Date.now() - (1000 * 60 * PromWrapper.ttlInMinutes));
- this.instances.forEach((instance, key) => {
- if (thresh > instance.time) {
- if (process.env['DEBUG_METRICS']) {
- console.log("Sweeping stale metric instance", this.name, {opts: instance.opts}, key);
- }
- return this.metric.remove(...Array.from(optsAsArgs(instance.opts, this.metric.labelNames) || []));
- }
- });
- if (thresh > this.lastAccess) {
- if (process.env['DEBUG_METRICS']) {
- console.log("Sweeping stale metric", this.name, thresh, this.lastAccess);
- }
- metrics.delete(this.name);
- return registry.removeSingleMetric(this.name);
- }
- }
- _execMethod(method, opts, value) {
- opts = extendOpts(opts, this.metric.labelNames);
- const key = optsKey(opts);
- if (key !== '') { this.instances.set(key, { time: new Date(), opts }); }
- this.lastAccess = new Date();
- return this.metric[method](opts, value);
- }
- }
- if (!PromWrapper.sweepRegistered) {
- if (process.env['DEBUG_METRICS']) {
- console.log("Registering sweep method");
- }
- PromWrapper.sweepRegistered = true;
- setInterval(
- function() {
- if (PromWrapper.ttlInMinutes) {
- if (process.env['DEBUG_METRICS']) {
- console.log("Sweeping metrics");
- }
- return metrics.forEach((metric, key) => {
- return metric.sweep();
- });
- }
- },
- 60000);
- }
- module.exports = PromWrapper;
|