@adalo/metrics 0.1.128 → 0.1.129

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,6 +15,7 @@ export class BaseMetricsClient {
15
15
  * @param {number} [config.intervalSec] Interval in seconds for pushing metrics
16
16
  * @param {boolean} [config.removeOldMetrics] Enable to clear metrics by service name
17
17
  * @param {function} [config.startupValidation] Add to validate on start push.
18
+ * @param {boolean} [config.disablePushgateway] Disable pushing to Pushgateway (use HTTP scraping instead)
18
19
  */
19
20
  constructor(config?: {
20
21
  appName?: string | undefined;
@@ -27,6 +28,7 @@ export class BaseMetricsClient {
27
28
  intervalSec?: number | undefined;
28
29
  removeOldMetrics?: boolean | undefined;
29
30
  startupValidation?: Function | undefined;
31
+ disablePushgateway?: boolean | undefined;
30
32
  });
31
33
  appName: string;
32
34
  dynoId: string;
@@ -37,6 +39,7 @@ export class BaseMetricsClient {
37
39
  authToken: string;
38
40
  intervalSec: number;
39
41
  startupValidation: Function | undefined;
42
+ disablePushgateway: boolean;
40
43
  prefixLogs: string;
41
44
  _registry: client.Registry<"text/plain; version=0.0.4; charset=utf-8">;
42
45
  defaultLabels: {
@@ -167,6 +170,8 @@ export class BaseMetricsClient {
167
170
  get metricsEnabled(): boolean;
168
171
  get metricsLogValues(): boolean;
169
172
  get registry(): client.Registry<"text/plain; version=0.0.4; charset=utf-8">;
173
+ getMetricsAsString(): Promise<string>;
174
+ metricsMiddleware(): (req: any, res: any) => Promise<void>;
170
175
  }
171
176
  import client = require("prom-client");
172
177
  //# sourceMappingURL=baseMetricsClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"baseMetricsClient.d.ts","sourceRoot":"","sources":["../../src/metrics/baseMetricsClient.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH;IACE;;;;;;;;;;;;OAYG;IACH;QAX2B,OAAO;QACP,MAAM;QACN,WAAW;QACV,OAAO;QACP,SAAS;QACV,cAAc;QACd,iBAAiB;QACjB,WAAW;QACV,gBAAgB;QACf,iBAAiB;OAkD7C;IA/CC,gBAA4E;IAC5E,eAAqE;IACrE,oBAG6B;IAC7B,iBAAuE;IACvE,mBAC+D;IAC/D,uBACoE;IACpE,kBAC0E;IAC1E,oBAGI;IACJ,wCAAiD;IAEjD,mBAAyF;IAEzF,uEAAsC;IAGtC;;;;MAIC;IAED,wEAOC;IACD,WAAgB;IAChB,aAAkB;IAClB,sBAA2B;IAE3B,mEAAmE;IACnE;YADkB,MAAM,SAAc,MAAM,GAAG,QAAQ,MAAM,CAAC;MACvC;IAMzB;;;;;;;;OAQG;IACH;QAN2B,IAAI,EAApB,MAAM;QACU,IAAI,EAApB,MAAM;QACuC,QAAQ,UAAzC,MAAM,GAAC,QAAQ,MAAM,CAAC;QACf,UAAU;UAC3B,OAAO,aAAa,EAAE,KAAK,CAuBvC;IAED;;;;;;;;;;;OAWG;IACH;QAR0B,IAAI,EAAnB,MAAM;QACS,IAAI,EAAnB,MAAM;QACY,UAAU;kBAEhB,MAAM,mBAAmB,MAAM,KAAK,IAAI,CAuB9D;IAED;;OAEG;IACH,6BAKC;IAED;;OAEG;IACH,kCA+BC;IAED,sEAuBC;IAED,iCAEC;IAED;;;;;;;;;OASG;IACH,iFAEC;IAED;;;OAGG;IACH,eAFa,QAAQ,IAAI,CAAC,CAOzB;IAED;;;;;;;;;OASG;IACH,yBA0FC;IAED;;;;;;;;;OASG;IACH;;;;;;sBAFa,QAAQ,IAAI,CAAC,CAUzB;IAED;;;;;;;OAOG;IACH;;;sBAFa,QAAQ,IAAI,CAAC,CAYzB;IAED;;;;;;OAMG;IACH,6BAHW,MAAM,EAAE,KACN,MAAM,EAAE,CAIpB;IAED;;;;MAEC;IAED,gCAGC;IAID,8BAEC;IAED,gCAEC;IAED,4EAEC;CACF"}
1
+ {"version":3,"file":"baseMetricsClient.d.ts","sourceRoot":"","sources":["../../src/metrics/baseMetricsClient.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH;IACE;;;;;;;;;;;;;OAaG;IACH;QAZ2B,OAAO;QACP,MAAM;QACN,WAAW;QACV,OAAO;QACP,SAAS;QACV,cAAc;QACd,iBAAiB;QACjB,WAAW;QACV,gBAAgB;QACf,iBAAiB;QAClB,kBAAkB;OAqD7C;IAlDC,gBAA4E;IAC5E,eAAqE;IACrE,oBAG6B;IAC7B,iBAAuE;IACvE,mBAC+D;IAC/D,uBACoE;IACpE,kBAC0E;IAC1E,oBAGI;IACJ,wCAAiD;IACjD,4BAEoD;IAEpD,mBAAyF;IAEzF,uEAAsC;IAGtC;;;;MAIC;IAED,wEAOC;IACD,WAAgB;IAChB,aAAkB;IAClB,sBAA2B;IAE3B,mEAAmE;IACnE;YADkB,MAAM,SAAc,MAAM,GAAG,QAAQ,MAAM,CAAC;MACvC;IAMzB;;;;;;;;OAQG;IACH;QAN2B,IAAI,EAApB,MAAM;QACU,IAAI,EAApB,MAAM;QACuC,QAAQ,UAAzC,MAAM,GAAC,QAAQ,MAAM,CAAC;QACf,UAAU;UAC3B,OAAO,aAAa,EAAE,KAAK,CAuBvC;IAED;;;;;;;;;;;OAWG;IACH;QAR0B,IAAI,EAAnB,MAAM;QACS,IAAI,EAAnB,MAAM;QACY,UAAU;kBAEhB,MAAM,mBAAmB,MAAM,KAAK,IAAI,CAuB9D;IAED;;OAEG;IACH,6BAKC;IAED;;OAEG;IACH,kCAiCC;IAED,sEAuBC;IAED,iCAEC;IAED;;;;;;;;;OASG;IACH,iFAEC;IAED;;;OAGG;IACH,eAFa,QAAQ,IAAI,CAAC,CAOzB;IAED;;;;;;;;;OASG;IACH,yBA0FC;IAED;;;;;;;;;OASG;IACH;;;;;;sBAFa,QAAQ,IAAI,CAAC,CAUzB;IAED;;;;;;;OAOG;IACH;;;sBAFa,QAAQ,IAAI,CAAC,CAezB;IAED;;;;;;OAMG;IACH,6BAHW,MAAM,EAAE,KACN,MAAM,EAAE,CAIpB;IAED;;;;MAEC;IAED,gCAGC;IAID,8BAEC;IAED,gCAEC;IAED,4EAEC;IAED,sCAEC;IAED,2DAWC;CACF"}
@@ -20,6 +20,7 @@ class BaseMetricsClient {
20
20
  * @param {number} [config.intervalSec] Interval in seconds for pushing metrics
21
21
  * @param {boolean} [config.removeOldMetrics] Enable to clear metrics by service name
22
22
  * @param {function} [config.startupValidation] Add to validate on start push.
23
+ * @param {boolean} [config.disablePushgateway] Disable pushing to Pushgateway (use HTTP scraping instead)
23
24
  */
24
25
  constructor(config = {}) {
25
26
  this.appName = config.appName || process.env.BUILD_APP_NAME || 'unknown-app';
@@ -31,6 +32,7 @@ class BaseMetricsClient {
31
32
  this.authToken = config.pushgatewaySecret || process.env.METRICS_PUSHGATEWAY_SECRET || '';
32
33
  this.intervalSec = config.intervalSec || parseInt(process.env.METRICS_INTERVAL_SEC || '', 10) || 15;
33
34
  this.startupValidation = config.startupValidation;
35
+ this.disablePushgateway = config.disablePushgateway ?? process.env.METRICS_DISABLE_PUSHGATEWAY === 'true';
34
36
  this.prefixLogs = `[${this.processType}] [${this.appName}] [${this.dynoId}] [Monitoring]`;
35
37
  this._registry = new client.Registry();
36
38
  client.collectDefaultMetrics({
@@ -143,7 +145,7 @@ class BaseMetricsClient {
143
145
  for (const [name, updateFn] of Object.entries(this.gaugeUpdaters)) {
144
146
  try {
145
147
  if (!updateFn) {
146
- return;
148
+ continue;
147
149
  }
148
150
  const result = updateFn();
149
151
  const val = result instanceof Promise ? await result : result;
@@ -152,7 +154,9 @@ class BaseMetricsClient {
152
154
  console.error(`${this.prefixLogs} Failed to update gauge ${name}:`, err);
153
155
  }
154
156
  }
155
- await this.gatewayPush();
157
+ if (!this.disablePushgateway) {
158
+ await this.gatewayPush();
159
+ }
156
160
  // this.clearAllCounters() //TODO: or uncommit or delete (based on grafana expectation)
157
161
 
158
162
  if (this.logValues) {
@@ -310,6 +314,9 @@ class BaseMetricsClient {
310
314
  * @returns {Promise<void>}
311
315
  */
312
316
  gatewayPush = async (params = {}) => {
317
+ if (this.disablePushgateway) {
318
+ return Promise.resolve();
319
+ }
313
320
  const groupings = {
314
321
  process_type: this.processType,
315
322
  instance: this.dynoId,
@@ -350,6 +357,21 @@ class BaseMetricsClient {
350
357
  get registry() {
351
358
  return this._registry;
352
359
  }
360
+ async getMetricsAsString() {
361
+ return this._registry.metrics();
362
+ }
363
+ metricsMiddleware() {
364
+ return async (req, res) => {
365
+ try {
366
+ const metrics = await this.getMetricsAsString();
367
+ res.set('Content-Type', client.register.contentType);
368
+ res.end(metrics);
369
+ } catch (err) {
370
+ console.error(`${this.prefixLogs} Failed to get metrics:`, err);
371
+ res.status(500).end('Failed to collect metrics');
372
+ }
373
+ };
374
+ }
353
375
  }
354
376
  module.exports = {
355
377
  BaseMetricsClient
@@ -1 +1 @@
1
- {"version":3,"file":"baseMetricsClient.js","names":["client","require","https","BaseMetricsClient","constructor","config","appName","process","env","BUILD_APP_NAME","dynoId","HOSTNAME","processType","BUILD_DYNO_PROCESS_TYPE","enabled","METRICS_ENABLED","logValues","METRICS_LOG_VALUES","pushgatewayUrl","METRICS_PUSHGATEWAY_URL","authToken","pushgatewaySecret","METRICS_PUSHGATEWAY_SECRET","intervalSec","parseInt","METRICS_INTERVAL_SEC","startupValidation","prefixLogs","_registry","Registry","collectDefaultMetrics","register","defaultLabels","app","dyno_id","process_type","gateway","Pushgateway","headers","Authorization","agent","Agent","keepAlive","gauges","counters","countersFunctions","gaugeUpdaters","_clearOldWorkers","removeOldMetrics","_setCleanupHandlers","createGauge","name","help","updateFn","labelNames","Object","keys","g","Gauge","registers","createCounter","c","Counter","data","value","inc","clearAllCounters","metricsLogValues","console","log","values","forEach","counter","reset","_pushMetrics","entries","result","val","Promise","undefined","set","err","error","gatewayPush","metrics","getMetricsAsJSON","JSON","stringify","_startPush","interval","customPushMetics","warn","setInterval","pushMetrics","catch","startPush","cleanup","gatewayDelete","exit","url","res","fetch","Accept","ok","status","text","metricRegex","labelRegex","uniqueLabelSets","Set","match","exec","rawLabels","lr","labels","job","add","size","oldLabelSets","map","s","parse","filter","instance","length","jobName","groupings","params","delete","push","withDefaultLabels","getDefaultLabels","on","metricsEnabled","registry","module","exports"],"sources":["../../src/metrics/baseMetricsClient.js"],"sourcesContent":["const client = require('prom-client')\nconst https = require('https')\n\n/**\n * BaseMetricsClient provides common functionality for all metrics clients.\n * Handles registry setup, pushgateway, default labels, and common operations.\n */\nclass BaseMetricsClient {\n /**\n * @param {Object} config\n * @param {string} [config.appName] Name of the application\n * @param {string} [config.dynoId] Dyno/instance ID\n * @param {string} [config.processType] Process type (web, worker, etc.)\n * @param {boolean} [config.enabled] Enable metrics collection\n * @param {boolean} [config.logValues] Log metrics values to console\n * @param {string} [config.pushgatewayUrl] PushGateway URL\n * @param {string} [config.pushgatewaySecret] PushGateway secret token\n * @param {number} [config.intervalSec] Interval in seconds for pushing metrics\n * @param {boolean} [config.removeOldMetrics] Enable to clear metrics by service name\n * @param {function} [config.startupValidation] Add to validate on start push.\n */\n constructor(config = {}) {\n this.appName = config.appName || process.env.BUILD_APP_NAME || 'unknown-app'\n this.dynoId = config.dynoId || process.env.HOSTNAME || 'unknown-dyno'\n this.processType =\n config.processType ||\n process.env.BUILD_DYNO_PROCESS_TYPE ||\n 'undefined_build_dyno_type'\n this.enabled = config.enabled ?? process.env.METRICS_ENABLED === 'true'\n this.logValues =\n config.logValues ?? process.env.METRICS_LOG_VALUES === 'true'\n this.pushgatewayUrl =\n config.pushgatewayUrl || process.env.METRICS_PUSHGATEWAY_URL || ''\n this.authToken =\n config.pushgatewaySecret || process.env.METRICS_PUSHGATEWAY_SECRET || ''\n this.intervalSec =\n config.intervalSec ||\n parseInt(process.env.METRICS_INTERVAL_SEC || '', 10) ||\n 15\n this.startupValidation = config.startupValidation\n\n this.prefixLogs = `[${this.processType}] [${this.appName}] [${this.dynoId}] [Monitoring]`\n\n this._registry = new client.Registry()\n client.collectDefaultMetrics({ register: this._registry })\n\n this.defaultLabels = {\n app: this.appName,\n dyno_id: this.dynoId,\n process_type: this.processType,\n }\n\n this.gateway = new client.Pushgateway(\n this.pushgatewayUrl,\n {\n headers: { Authorization: `Basic ${this.authToken}` },\n agent: new https.Agent({ keepAlive: true }),\n },\n this._registry\n )\n this.gauges = {}\n this.counters = {}\n this.countersFunctions = {}\n\n /** @type {Object<string, function(): number | Promise<number>>} */\n this.gaugeUpdaters = {}\n\n this._clearOldWorkers(config.removeOldMetrics)\n this._setCleanupHandlers()\n }\n\n /**\n * Create a gauge metric.\n * @param {Object} options - Gauge configuration\n * @param {string} options.name - Name of the gauge\n * @param {string} options.help - Help text describing the gauge\n * @param {function(): number|Promise<number>} [options.updateFn] - Optional function returning the gauge value\n * @param {string[]} [options.labelNames] - Optional custom label names\n * @returns {import('prom-client').Gauge} The created Prometheus gauge\n */\n createGauge = ({\n name,\n help,\n updateFn,\n labelNames = Object.keys(this.defaultLabels),\n }) => {\n if (this.gauges[name]) return this.gauges[name]\n\n const g = new client.Gauge({\n name,\n help,\n labelNames,\n registers: [this._registry],\n })\n this.gauges[name] = g\n\n if (updateFn && typeof updateFn === 'function') {\n this.gaugeUpdaters[name] = updateFn\n }\n\n return g\n }\n\n /**\n * Create a Prometheus Counter metric.\n *\n * @param {Object} params - Counter configuration\n * @param {string} params.name - Metric name\n * @param {string} params.help - Metric description\n * @param {string[]} [params.labelNames] - Optional list of label names. Defaults to this.defaultLabels keys.\n *\n * @returns {(labels?: Object, incrementValue?: number) => void}\n * A function to increment the counter.\n * Usage: (labels?, incrementValue?)\n */\n createCounter({ name, help, labelNames = Object.keys(this.defaultLabels) }) {\n if (this.counters[name]) return this.countersFunctions[name]\n\n const c = new client.Counter({\n name,\n help,\n labelNames,\n registers: [this._registry],\n })\n this.counters[name] = c\n\n this.countersFunctions = {\n ...this.countersFunctions,\n [name]: (data = {}, value = 1) => {\n c.inc({ ...this.defaultLabels, ...data }, value)\n },\n }\n\n return this.countersFunctions[name]\n }\n\n /**\n * Clear all collected counters\n */\n clearAllCounters = () => {\n if (this.metricsLogValues) {\n console.log('Counters to clear: ', Object.keys(this.counters))\n }\n Object.values(this.counters).forEach(counter => counter.reset())\n }\n\n /**\n * Push all gauges and counters to PushGateway and optionally log.\n */\n _pushMetrics = async () => {\n try {\n for (const [name, updateFn] of Object.entries(this.gaugeUpdaters)) {\n try {\n if (!updateFn) {\n return\n }\n const result = updateFn()\n const val = result instanceof Promise ? await result : result\n if (val !== undefined) this.gauges[name].set(this.defaultLabels, val)\n } catch (err) {\n console.error(\n `${this.prefixLogs} Failed to update gauge ${name}:`,\n err\n )\n }\n }\n\n await this.gatewayPush()\n // this.clearAllCounters() //TODO: or uncommit or delete (based on grafana expectation)\n\n if (this.logValues) {\n const metrics = await this._registry.getMetricsAsJSON()\n console.log(\n `${this.prefixLogs} Metrics:\\n`,\n JSON.stringify(metrics, null, 2)\n )\n }\n } catch (err) {\n console.error(`${this.prefixLogs} Failed to push metrics:`, err)\n }\n }\n\n _startPush = (interval = this.intervalSec, customPushMetics = undefined) => {\n if (!this.enabled) {\n console.warn(`${this.prefixLogs} Metrics disabled`)\n return\n }\n\n if (this.startupValidation && !this.startupValidation()) {\n return\n }\n\n if (customPushMetics && typeof customPushMetics === 'function') {\n setInterval(() => customPushMetics(), interval * 1000)\n } else {\n setInterval(() => {\n this.pushMetrics().catch(err => {\n console.error(`${this.prefixLogs} Failed to push metrics:`, err)\n })\n }, interval * 1000)\n }\n\n console.warn(\n `${this.prefixLogs} Metrics collection started. (interval: ${this.intervalSec}s)`\n )\n }\n\n pushMetrics = async () => {\n return this._pushMetrics()\n }\n\n /**\n * Start periodic metrics collection and push.\n *\n * This method wraps the internal `_startPush` method.\n * If a `customPushMetrics` function is provided, it will be executed\n * at the given interval instead of the default `pushMetrics` behavior.\n *\n * @param {number} [interval=this.intervalSec] - Interval in seconds between pushes.\n * @param {() => void | Promise<void>} [customPushMetrics] - Optional custom push function. If provided, Prometheus push is skipped.\n */\n startPush = (interval, customPushMetics = undefined) => {\n this._startPush(interval, customPushMetics)\n }\n\n /**\n * Cleanup metrics and exit process.\n * @returns {Promise<void>}\n */\n cleanup = async () => {\n if (this.enabled) {\n await this.gatewayDelete()\n }\n process.exit(0)\n }\n\n /**\n * Remove old/stale dyno/instance metrics from PushGateway.\n *\n * Compares existing PushGateway metrics for this job and deletes any instances\n * that do not match the current dynoId.\n *\n * @param {boolean} removeOldMetrics If true, performs cleanup; otherwise does nothing\n * @returns {Promise<void>}\n * @private\n */\n _clearOldWorkers = async removeOldMetrics => {\n if (!removeOldMetrics) return\n\n try {\n const url = `${this.pushgatewayUrl}/metrics`\n const res = await fetch(url, {\n headers: {\n Authorization: `Basic ${this.authToken}`,\n Accept: 'text/plain',\n },\n })\n\n if (!res.ok) {\n console.error(\n `${this.prefixLogs} Failed to fetch metrics: ${res.status}`\n )\n return\n }\n\n const text = await res.text()\n\n const metricRegex = /([a-zA-Z_:][a-zA-Z0-9_:]*)\\{([^}]*)\\}/gm\n const labelRegex = /(\\w+)=\"([^\"]*)\"/g\n\n const uniqueLabelSets = new Set()\n\n let match\n // eslint-disable-next-line no-cond-assign\n while ((match = metricRegex.exec(text)) !== null) {\n const rawLabels = match[2]\n let lr\n const labels = {}\n\n // eslint-disable-next-line no-cond-assign\n while ((lr = labelRegex.exec(rawLabels)) !== null) {\n // eslint-disable-next-line prefer-destructuring\n labels[lr[1]] = lr[2]\n }\n\n if (\n labels.job === this.appName &&\n labels.process_type === this.processType\n ) {\n uniqueLabelSets.add(JSON.stringify(labels))\n }\n }\n\n if (uniqueLabelSets.size === 0) {\n console.log(\n `${this.prefixLogs} No metrics found for job ${this.appName}`\n )\n return\n }\n\n const oldLabelSets = [...uniqueLabelSets]\n .map(s => JSON.parse(s))\n .filter(\n labels =>\n labels.instance &&\n labels.instance !== this.dynoId &&\n labels.process_type === this.processType\n )\n\n if (oldLabelSets.length === 0) {\n console.log(`${this.prefixLogs} No old dynos to delete.`)\n return\n }\n\n for (const labels of oldLabelSets) {\n try {\n await this.gatewayDelete({ jobName: this.appName, groupings: labels })\n console.log(\n `${this.prefixLogs} Deleted metrics for dyno: ${\n labels.instance\n }, labels: ${Object.keys(labels)} `\n )\n } catch (err) {\n console.error(\n `${this.prefixLogs} Failed to delete metrics for ${labels.instance}:`,\n err\n )\n }\n }\n\n console.log(\n `${this.prefixLogs} Cleared all old instances for job ${this.appName}`\n )\n } catch (err) {\n console.error(`${this.prefixLogs} Error deleting old metrics:`, err)\n }\n }\n\n /**\n * Delete metrics for this job/instance from PushGateway.\n *\n * @param {Object} [params]\n * @param {string} [params.jobName] Job name (defaults to appName)\n * @param {Object} [params.groupings] Grouping labels\n * @param {string} [params.groupings.process_type] Process type label\n * @param {string} [params.groupings.instance] Instance/dyno ID\n * @returns {Promise<void>}\n */\n gatewayDelete = async (params = {}) => {\n return this.gateway.delete({\n jobName: params.jobName || this.appName,\n groupings: params.groupings || {\n process_type: this.processType,\n instance: this.dynoId,\n },\n })\n }\n\n /**\n * Push metrics to PushGateway.\n *\n * @param {object} [params]\n * @param {string} [params.jobName]\n * @param {object} [params.groupings]\n * @returns {Promise<void>}\n */\n gatewayPush = async (params = {}) => {\n const groupings = {\n process_type: this.processType,\n instance: this.dynoId,\n ...(params.groupings || {}),\n }\n return this.gateway.push({\n jobName: params.jobName || this.appName,\n groupings,\n })\n }\n\n /**\n * Merge the default metric labels (`app`, `dyno_id`, `process_type`)\n * with custom label names.\n *\n * @param {string[]} labels Additional label names\n * @returns {string[]} Combined label names\n */\n withDefaultLabels = (labels = []) => {\n return [...Object.keys(this.defaultLabels), ...labels]\n }\n\n getDefaultLabels = (labels = []) => {\n return this.defaultLabels\n }\n\n _setCleanupHandlers = () => {\n process.on('SIGINT', this.cleanup)\n process.on('SIGTERM', this.cleanup)\n }\n\n // GETTERS\n\n get metricsEnabled() {\n return this.enabled\n }\n\n get metricsLogValues() {\n return this.logValues\n }\n\n get registry() {\n return this._registry\n }\n}\n\nmodule.exports = { BaseMetricsClient }\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"baseMetricsClient.js","names":["client","require","https","BaseMetricsClient","constructor","config","appName","process","env","BUILD_APP_NAME","dynoId","HOSTNAME","processType","BUILD_DYNO_PROCESS_TYPE","enabled","METRICS_ENABLED","logValues","METRICS_LOG_VALUES","pushgatewayUrl","METRICS_PUSHGATEWAY_URL","authToken","pushgatewaySecret","METRICS_PUSHGATEWAY_SECRET","intervalSec","parseInt","METRICS_INTERVAL_SEC","startupValidation","disablePushgateway","METRICS_DISABLE_PUSHGATEWAY","prefixLogs","_registry","Registry","collectDefaultMetrics","register","defaultLabels","app","dyno_id","process_type","gateway","Pushgateway","headers","Authorization","agent","Agent","keepAlive","gauges","counters","countersFunctions","gaugeUpdaters","_clearOldWorkers","removeOldMetrics","_setCleanupHandlers","createGauge","name","help","updateFn","labelNames","Object","keys","g","Gauge","registers","createCounter","c","Counter","data","value","inc","clearAllCounters","metricsLogValues","console","log","values","forEach","counter","reset","_pushMetrics","entries","result","val","Promise","undefined","set","err","error","gatewayPush","metrics","getMetricsAsJSON","JSON","stringify","_startPush","interval","customPushMetics","warn","setInterval","pushMetrics","catch","startPush","cleanup","gatewayDelete","exit","url","res","fetch","Accept","ok","status","text","metricRegex","labelRegex","uniqueLabelSets","Set","match","exec","rawLabels","lr","labels","job","add","size","oldLabelSets","map","s","parse","filter","instance","length","jobName","groupings","params","delete","resolve","push","withDefaultLabels","getDefaultLabels","on","metricsEnabled","registry","getMetricsAsString","metricsMiddleware","req","contentType","end","module","exports"],"sources":["../../src/metrics/baseMetricsClient.js"],"sourcesContent":["const client = require('prom-client')\nconst https = require('https')\n\n/**\n * BaseMetricsClient provides common functionality for all metrics clients.\n * Handles registry setup, pushgateway, default labels, and common operations.\n */\nclass BaseMetricsClient {\n /**\n * @param {Object} config\n * @param {string} [config.appName] Name of the application\n * @param {string} [config.dynoId] Dyno/instance ID\n * @param {string} [config.processType] Process type (web, worker, etc.)\n * @param {boolean} [config.enabled] Enable metrics collection\n * @param {boolean} [config.logValues] Log metrics values to console\n * @param {string} [config.pushgatewayUrl] PushGateway URL\n * @param {string} [config.pushgatewaySecret] PushGateway secret token\n * @param {number} [config.intervalSec] Interval in seconds for pushing metrics\n * @param {boolean} [config.removeOldMetrics] Enable to clear metrics by service name\n * @param {function} [config.startupValidation] Add to validate on start push.\n * @param {boolean} [config.disablePushgateway] Disable pushing to Pushgateway (use HTTP scraping instead)\n */\n constructor(config = {}) {\n this.appName = config.appName || process.env.BUILD_APP_NAME || 'unknown-app'\n this.dynoId = config.dynoId || process.env.HOSTNAME || 'unknown-dyno'\n this.processType =\n config.processType ||\n process.env.BUILD_DYNO_PROCESS_TYPE ||\n 'undefined_build_dyno_type'\n this.enabled = config.enabled ?? process.env.METRICS_ENABLED === 'true'\n this.logValues =\n config.logValues ?? process.env.METRICS_LOG_VALUES === 'true'\n this.pushgatewayUrl =\n config.pushgatewayUrl || process.env.METRICS_PUSHGATEWAY_URL || ''\n this.authToken =\n config.pushgatewaySecret || process.env.METRICS_PUSHGATEWAY_SECRET || ''\n this.intervalSec =\n config.intervalSec ||\n parseInt(process.env.METRICS_INTERVAL_SEC || '', 10) ||\n 15\n this.startupValidation = config.startupValidation\n this.disablePushgateway =\n config.disablePushgateway ??\n process.env.METRICS_DISABLE_PUSHGATEWAY === 'true'\n\n this.prefixLogs = `[${this.processType}] [${this.appName}] [${this.dynoId}] [Monitoring]`\n\n this._registry = new client.Registry()\n client.collectDefaultMetrics({ register: this._registry })\n\n this.defaultLabels = {\n app: this.appName,\n dyno_id: this.dynoId,\n process_type: this.processType,\n }\n\n this.gateway = new client.Pushgateway(\n this.pushgatewayUrl,\n {\n headers: { Authorization: `Basic ${this.authToken}` },\n agent: new https.Agent({ keepAlive: true }),\n },\n this._registry\n )\n this.gauges = {}\n this.counters = {}\n this.countersFunctions = {}\n\n /** @type {Object<string, function(): number | Promise<number>>} */\n this.gaugeUpdaters = {}\n\n this._clearOldWorkers(config.removeOldMetrics)\n this._setCleanupHandlers()\n }\n\n /**\n * Create a gauge metric.\n * @param {Object} options - Gauge configuration\n * @param {string} options.name - Name of the gauge\n * @param {string} options.help - Help text describing the gauge\n * @param {function(): number|Promise<number>} [options.updateFn] - Optional function returning the gauge value\n * @param {string[]} [options.labelNames] - Optional custom label names\n * @returns {import('prom-client').Gauge} The created Prometheus gauge\n */\n createGauge = ({\n name,\n help,\n updateFn,\n labelNames = Object.keys(this.defaultLabels),\n }) => {\n if (this.gauges[name]) return this.gauges[name]\n\n const g = new client.Gauge({\n name,\n help,\n labelNames,\n registers: [this._registry],\n })\n this.gauges[name] = g\n\n if (updateFn && typeof updateFn === 'function') {\n this.gaugeUpdaters[name] = updateFn\n }\n\n return g\n }\n\n /**\n * Create a Prometheus Counter metric.\n *\n * @param {Object} params - Counter configuration\n * @param {string} params.name - Metric name\n * @param {string} params.help - Metric description\n * @param {string[]} [params.labelNames] - Optional list of label names. Defaults to this.defaultLabels keys.\n *\n * @returns {(labels?: Object, incrementValue?: number) => void}\n * A function to increment the counter.\n * Usage: (labels?, incrementValue?)\n */\n createCounter({ name, help, labelNames = Object.keys(this.defaultLabels) }) {\n if (this.counters[name]) return this.countersFunctions[name]\n\n const c = new client.Counter({\n name,\n help,\n labelNames,\n registers: [this._registry],\n })\n this.counters[name] = c\n\n this.countersFunctions = {\n ...this.countersFunctions,\n [name]: (data = {}, value = 1) => {\n c.inc({ ...this.defaultLabels, ...data }, value)\n },\n }\n\n return this.countersFunctions[name]\n }\n\n /**\n * Clear all collected counters\n */\n clearAllCounters = () => {\n if (this.metricsLogValues) {\n console.log('Counters to clear: ', Object.keys(this.counters))\n }\n Object.values(this.counters).forEach(counter => counter.reset())\n }\n\n /**\n * Push all gauges and counters to PushGateway and optionally log.\n */\n _pushMetrics = async () => {\n try {\n for (const [name, updateFn] of Object.entries(this.gaugeUpdaters)) {\n try {\n if (!updateFn) {\n continue\n }\n const result = updateFn()\n const val = result instanceof Promise ? await result : result\n if (val !== undefined) this.gauges[name].set(this.defaultLabels, val)\n } catch (err) {\n console.error(\n `${this.prefixLogs} Failed to update gauge ${name}:`,\n err\n )\n }\n }\n\n if (!this.disablePushgateway) {\n await this.gatewayPush()\n }\n // this.clearAllCounters() //TODO: or uncommit or delete (based on grafana expectation)\n\n if (this.logValues) {\n const metrics = await this._registry.getMetricsAsJSON()\n console.log(\n `${this.prefixLogs} Metrics:\\n`,\n JSON.stringify(metrics, null, 2)\n )\n }\n } catch (err) {\n console.error(`${this.prefixLogs} Failed to push metrics:`, err)\n }\n }\n\n _startPush = (interval = this.intervalSec, customPushMetics = undefined) => {\n if (!this.enabled) {\n console.warn(`${this.prefixLogs} Metrics disabled`)\n return\n }\n\n if (this.startupValidation && !this.startupValidation()) {\n return\n }\n\n if (customPushMetics && typeof customPushMetics === 'function') {\n setInterval(() => customPushMetics(), interval * 1000)\n } else {\n setInterval(() => {\n this.pushMetrics().catch(err => {\n console.error(`${this.prefixLogs} Failed to push metrics:`, err)\n })\n }, interval * 1000)\n }\n\n console.warn(\n `${this.prefixLogs} Metrics collection started. (interval: ${this.intervalSec}s)`\n )\n }\n\n pushMetrics = async () => {\n return this._pushMetrics()\n }\n\n /**\n * Start periodic metrics collection and push.\n *\n * This method wraps the internal `_startPush` method.\n * If a `customPushMetrics` function is provided, it will be executed\n * at the given interval instead of the default `pushMetrics` behavior.\n *\n * @param {number} [interval=this.intervalSec] - Interval in seconds between pushes.\n * @param {() => void | Promise<void>} [customPushMetrics] - Optional custom push function. If provided, Prometheus push is skipped.\n */\n startPush = (interval, customPushMetics = undefined) => {\n this._startPush(interval, customPushMetics)\n }\n\n /**\n * Cleanup metrics and exit process.\n * @returns {Promise<void>}\n */\n cleanup = async () => {\n if (this.enabled) {\n await this.gatewayDelete()\n }\n process.exit(0)\n }\n\n /**\n * Remove old/stale dyno/instance metrics from PushGateway.\n *\n * Compares existing PushGateway metrics for this job and deletes any instances\n * that do not match the current dynoId.\n *\n * @param {boolean} removeOldMetrics If true, performs cleanup; otherwise does nothing\n * @returns {Promise<void>}\n * @private\n */\n _clearOldWorkers = async removeOldMetrics => {\n if (!removeOldMetrics) return\n\n try {\n const url = `${this.pushgatewayUrl}/metrics`\n const res = await fetch(url, {\n headers: {\n Authorization: `Basic ${this.authToken}`,\n Accept: 'text/plain',\n },\n })\n\n if (!res.ok) {\n console.error(\n `${this.prefixLogs} Failed to fetch metrics: ${res.status}`\n )\n return\n }\n\n const text = await res.text()\n\n const metricRegex = /([a-zA-Z_:][a-zA-Z0-9_:]*)\\{([^}]*)\\}/gm\n const labelRegex = /(\\w+)=\"([^\"]*)\"/g\n\n const uniqueLabelSets = new Set()\n\n let match\n // eslint-disable-next-line no-cond-assign\n while ((match = metricRegex.exec(text)) !== null) {\n const rawLabels = match[2]\n let lr\n const labels = {}\n\n // eslint-disable-next-line no-cond-assign\n while ((lr = labelRegex.exec(rawLabels)) !== null) {\n // eslint-disable-next-line prefer-destructuring\n labels[lr[1]] = lr[2]\n }\n\n if (\n labels.job === this.appName &&\n labels.process_type === this.processType\n ) {\n uniqueLabelSets.add(JSON.stringify(labels))\n }\n }\n\n if (uniqueLabelSets.size === 0) {\n console.log(\n `${this.prefixLogs} No metrics found for job ${this.appName}`\n )\n return\n }\n\n const oldLabelSets = [...uniqueLabelSets]\n .map(s => JSON.parse(s))\n .filter(\n labels =>\n labels.instance &&\n labels.instance !== this.dynoId &&\n labels.process_type === this.processType\n )\n\n if (oldLabelSets.length === 0) {\n console.log(`${this.prefixLogs} No old dynos to delete.`)\n return\n }\n\n for (const labels of oldLabelSets) {\n try {\n await this.gatewayDelete({ jobName: this.appName, groupings: labels })\n console.log(\n `${this.prefixLogs} Deleted metrics for dyno: ${\n labels.instance\n }, labels: ${Object.keys(labels)} `\n )\n } catch (err) {\n console.error(\n `${this.prefixLogs} Failed to delete metrics for ${labels.instance}:`,\n err\n )\n }\n }\n\n console.log(\n `${this.prefixLogs} Cleared all old instances for job ${this.appName}`\n )\n } catch (err) {\n console.error(`${this.prefixLogs} Error deleting old metrics:`, err)\n }\n }\n\n /**\n * Delete metrics for this job/instance from PushGateway.\n *\n * @param {Object} [params]\n * @param {string} [params.jobName] Job name (defaults to appName)\n * @param {Object} [params.groupings] Grouping labels\n * @param {string} [params.groupings.process_type] Process type label\n * @param {string} [params.groupings.instance] Instance/dyno ID\n * @returns {Promise<void>}\n */\n gatewayDelete = async (params = {}) => {\n return this.gateway.delete({\n jobName: params.jobName || this.appName,\n groupings: params.groupings || {\n process_type: this.processType,\n instance: this.dynoId,\n },\n })\n }\n\n /**\n * Push metrics to PushGateway.\n *\n * @param {object} [params]\n * @param {string} [params.jobName]\n * @param {object} [params.groupings]\n * @returns {Promise<void>}\n */\n gatewayPush = async (params = {}) => {\n if (this.disablePushgateway) {\n return Promise.resolve()\n }\n const groupings = {\n process_type: this.processType,\n instance: this.dynoId,\n ...(params.groupings || {}),\n }\n return this.gateway.push({\n jobName: params.jobName || this.appName,\n groupings,\n })\n }\n\n /**\n * Merge the default metric labels (`app`, `dyno_id`, `process_type`)\n * with custom label names.\n *\n * @param {string[]} labels Additional label names\n * @returns {string[]} Combined label names\n */\n withDefaultLabels = (labels = []) => {\n return [...Object.keys(this.defaultLabels), ...labels]\n }\n\n getDefaultLabels = (labels = []) => {\n return this.defaultLabels\n }\n\n _setCleanupHandlers = () => {\n process.on('SIGINT', this.cleanup)\n process.on('SIGTERM', this.cleanup)\n }\n\n // GETTERS\n\n get metricsEnabled() {\n return this.enabled\n }\n\n get metricsLogValues() {\n return this.logValues\n }\n\n get registry() {\n return this._registry\n }\n\n async getMetricsAsString() {\n return this._registry.metrics()\n }\n\n metricsMiddleware() {\n return async (req, res) => {\n try {\n const metrics = await this.getMetricsAsString()\n res.set('Content-Type', client.register.contentType)\n res.end(metrics)\n } catch (err) {\n console.error(`${this.prefixLogs} Failed to get metrics:`, err)\n res.status(500).end('Failed to collect metrics')\n }\n }\n }\n}\n\nmodule.exports = { BaseMetricsClient }\n"],"mappings":";;AAAA,MAAMA,MAAM,GAAGC,OAAO,CAAC,aAAa,CAAC;AACrC,MAAMC,KAAK,GAAGD,OAAO,CAAC,OAAO,CAAC;;AAE9B;AACA;AACA;AACA;AACA,MAAME,iBAAiB,CAAC;EACtB;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,WAAWA,CAACC,MAAM,GAAG,CAAC,CAAC,EAAE;IACvB,IAAI,CAACC,OAAO,GAAGD,MAAM,CAACC,OAAO,IAAIC,OAAO,CAACC,GAAG,CAACC,cAAc,IAAI,aAAa;IAC5E,IAAI,CAACC,MAAM,GAAGL,MAAM,CAACK,MAAM,IAAIH,OAAO,CAACC,GAAG,CAACG,QAAQ,IAAI,cAAc;IACrE,IAAI,CAACC,WAAW,GACdP,MAAM,CAACO,WAAW,IAClBL,OAAO,CAACC,GAAG,CAACK,uBAAuB,IACnC,2BAA2B;IAC7B,IAAI,CAACC,OAAO,GAAGT,MAAM,CAACS,OAAO,IAAIP,OAAO,CAACC,GAAG,CAACO,eAAe,KAAK,MAAM;IACvE,IAAI,CAACC,SAAS,GACZX,MAAM,CAACW,SAAS,IAAIT,OAAO,CAACC,GAAG,CAACS,kBAAkB,KAAK,MAAM;IAC/D,IAAI,CAACC,cAAc,GACjBb,MAAM,CAACa,cAAc,IAAIX,OAAO,CAACC,GAAG,CAACW,uBAAuB,IAAI,EAAE;IACpE,IAAI,CAACC,SAAS,GACZf,MAAM,CAACgB,iBAAiB,IAAId,OAAO,CAACC,GAAG,CAACc,0BAA0B,IAAI,EAAE;IAC1E,IAAI,CAACC,WAAW,GACdlB,MAAM,CAACkB,WAAW,IAClBC,QAAQ,CAACjB,OAAO,CAACC,GAAG,CAACiB,oBAAoB,IAAI,EAAE,EAAE,EAAE,CAAC,IACpD,EAAE;IACJ,IAAI,CAACC,iBAAiB,GAAGrB,MAAM,CAACqB,iBAAiB;IACjD,IAAI,CAACC,kBAAkB,GACrBtB,MAAM,CAACsB,kBAAkB,IACzBpB,OAAO,CAACC,GAAG,CAACoB,2BAA2B,KAAK,MAAM;IAEpD,IAAI,CAACC,UAAU,GAAG,IAAI,IAAI,CAACjB,WAAW,MAAM,IAAI,CAACN,OAAO,MAAM,IAAI,CAACI,MAAM,gBAAgB;IAEzF,IAAI,CAACoB,SAAS,GAAG,IAAI9B,MAAM,CAAC+B,QAAQ,CAAC,CAAC;IACtC/B,MAAM,CAACgC,qBAAqB,CAAC;MAAEC,QAAQ,EAAE,IAAI,CAACH;IAAU,CAAC,CAAC;IAE1D,IAAI,CAACI,aAAa,GAAG;MACnBC,GAAG,EAAE,IAAI,CAAC7B,OAAO;MACjB8B,OAAO,EAAE,IAAI,CAAC1B,MAAM;MACpB2B,YAAY,EAAE,IAAI,CAACzB;IACrB,CAAC;IAED,IAAI,CAAC0B,OAAO,GAAG,IAAItC,MAAM,CAACuC,WAAW,CACnC,IAAI,CAACrB,cAAc,EACnB;MACEsB,OAAO,EAAE;QAAEC,aAAa,EAAE,SAAS,IAAI,CAACrB,SAAS;MAAG,CAAC;MACrDsB,KAAK,EAAE,IAAIxC,KAAK,CAACyC,KAAK,CAAC;QAAEC,SAAS,EAAE;MAAK,CAAC;IAC5C,CAAC,EACD,IAAI,CAACd,SACP,CAAC;IACD,IAAI,CAACe,MAAM,GAAG,CAAC,CAAC;IAChB,IAAI,CAACC,QAAQ,GAAG,CAAC,CAAC;IAClB,IAAI,CAACC,iBAAiB,GAAG,CAAC,CAAC;;IAE3B;IACA,IAAI,CAACC,aAAa,GAAG,CAAC,CAAC;IAEvB,IAAI,CAACC,gBAAgB,CAAC5C,MAAM,CAAC6C,gBAAgB,CAAC;IAC9C,IAAI,CAACC,mBAAmB,CAAC,CAAC;EAC5B;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,WAAW,GAAGA,CAAC;IACbC,IAAI;IACJC,IAAI;IACJC,QAAQ;IACRC,UAAU,GAAGC,MAAM,CAACC,IAAI,CAAC,IAAI,CAACxB,aAAa;EAC7C,CAAC,KAAK;IACJ,IAAI,IAAI,CAACW,MAAM,CAACQ,IAAI,CAAC,EAAE,OAAO,IAAI,CAACR,MAAM,CAACQ,IAAI,CAAC;IAE/C,MAAMM,CAAC,GAAG,IAAI3D,MAAM,CAAC4D,KAAK,CAAC;MACzBP,IAAI;MACJC,IAAI;MACJE,UAAU;MACVK,SAAS,EAAE,CAAC,IAAI,CAAC/B,SAAS;IAC5B,CAAC,CAAC;IACF,IAAI,CAACe,MAAM,CAACQ,IAAI,CAAC,GAAGM,CAAC;IAErB,IAAIJ,QAAQ,IAAI,OAAOA,QAAQ,KAAK,UAAU,EAAE;MAC9C,IAAI,CAACP,aAAa,CAACK,IAAI,CAAC,GAAGE,QAAQ;IACrC;IAEA,OAAOI,CAAC;EACV,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEG,aAAaA,CAAC;IAAET,IAAI;IAAEC,IAAI;IAAEE,UAAU,GAAGC,MAAM,CAACC,IAAI,CAAC,IAAI,CAACxB,aAAa;EAAE,CAAC,EAAE;IAC1E,IAAI,IAAI,CAACY,QAAQ,CAACO,IAAI,CAAC,EAAE,OAAO,IAAI,CAACN,iBAAiB,CAACM,IAAI,CAAC;IAE5D,MAAMU,CAAC,GAAG,IAAI/D,MAAM,CAACgE,OAAO,CAAC;MAC3BX,IAAI;MACJC,IAAI;MACJE,UAAU;MACVK,SAAS,EAAE,CAAC,IAAI,CAAC/B,SAAS;IAC5B,CAAC,CAAC;IACF,IAAI,CAACgB,QAAQ,CAACO,IAAI,CAAC,GAAGU,CAAC;IAEvB,IAAI,CAAChB,iBAAiB,GAAG;MACvB,GAAG,IAAI,CAACA,iBAAiB;MACzB,CAACM,IAAI,GAAG,CAACY,IAAI,GAAG,CAAC,CAAC,EAAEC,KAAK,GAAG,CAAC,KAAK;QAChCH,CAAC,CAACI,GAAG,CAAC;UAAE,GAAG,IAAI,CAACjC,aAAa;UAAE,GAAG+B;QAAK,CAAC,EAAEC,KAAK,CAAC;MAClD;IACF,CAAC;IAED,OAAO,IAAI,CAACnB,iBAAiB,CAACM,IAAI,CAAC;EACrC;;EAEA;AACF;AACA;EACEe,gBAAgB,GAAGA,CAAA,KAAM;IACvB,IAAI,IAAI,CAACC,gBAAgB,EAAE;MACzBC,OAAO,CAACC,GAAG,CAAC,qBAAqB,EAAEd,MAAM,CAACC,IAAI,CAAC,IAAI,CAACZ,QAAQ,CAAC,CAAC;IAChE;IACAW,MAAM,CAACe,MAAM,CAAC,IAAI,CAAC1B,QAAQ,CAAC,CAAC2B,OAAO,CAACC,OAAO,IAAIA,OAAO,CAACC,KAAK,CAAC,CAAC,CAAC;EAClE,CAAC;;EAED;AACF;AACA;EACEC,YAAY,GAAG,MAAAA,CAAA,KAAY;IACzB,IAAI;MACF,KAAK,MAAM,CAACvB,IAAI,EAAEE,QAAQ,CAAC,IAAIE,MAAM,CAACoB,OAAO,CAAC,IAAI,CAAC7B,aAAa,CAAC,EAAE;QACjE,IAAI;UACF,IAAI,CAACO,QAAQ,EAAE;YACb;UACF;UACA,MAAMuB,MAAM,GAAGvB,QAAQ,CAAC,CAAC;UACzB,MAAMwB,GAAG,GAAGD,MAAM,YAAYE,OAAO,GAAG,MAAMF,MAAM,GAAGA,MAAM;UAC7D,IAAIC,GAAG,KAAKE,SAAS,EAAE,IAAI,CAACpC,MAAM,CAACQ,IAAI,CAAC,CAAC6B,GAAG,CAAC,IAAI,CAAChD,aAAa,EAAE6C,GAAG,CAAC;QACvE,CAAC,CAAC,OAAOI,GAAG,EAAE;UACZb,OAAO,CAACc,KAAK,CACX,GAAG,IAAI,CAACvD,UAAU,2BAA2BwB,IAAI,GAAG,EACpD8B,GACF,CAAC;QACH;MACF;MAEA,IAAI,CAAC,IAAI,CAACxD,kBAAkB,EAAE;QAC5B,MAAM,IAAI,CAAC0D,WAAW,CAAC,CAAC;MAC1B;MACA;;MAEA,IAAI,IAAI,CAACrE,SAAS,EAAE;QAClB,MAAMsE,OAAO,GAAG,MAAM,IAAI,CAACxD,SAAS,CAACyD,gBAAgB,CAAC,CAAC;QACvDjB,OAAO,CAACC,GAAG,CACT,GAAG,IAAI,CAAC1C,UAAU,aAAa,EAC/B2D,IAAI,CAACC,SAAS,CAACH,OAAO,EAAE,IAAI,EAAE,CAAC,CACjC,CAAC;MACH;IACF,CAAC,CAAC,OAAOH,GAAG,EAAE;MACZb,OAAO,CAACc,KAAK,CAAC,GAAG,IAAI,CAACvD,UAAU,0BAA0B,EAAEsD,GAAG,CAAC;IAClE;EACF,CAAC;EAEDO,UAAU,GAAGA,CAACC,QAAQ,GAAG,IAAI,CAACpE,WAAW,EAAEqE,gBAAgB,GAAGX,SAAS,KAAK;IAC1E,IAAI,CAAC,IAAI,CAACnE,OAAO,EAAE;MACjBwD,OAAO,CAACuB,IAAI,CAAC,GAAG,IAAI,CAAChE,UAAU,mBAAmB,CAAC;MACnD;IACF;IAEA,IAAI,IAAI,CAACH,iBAAiB,IAAI,CAAC,IAAI,CAACA,iBAAiB,CAAC,CAAC,EAAE;MACvD;IACF;IAEA,IAAIkE,gBAAgB,IAAI,OAAOA,gBAAgB,KAAK,UAAU,EAAE;MAC9DE,WAAW,CAAC,MAAMF,gBAAgB,CAAC,CAAC,EAAED,QAAQ,GAAG,IAAI,CAAC;IACxD,CAAC,MAAM;MACLG,WAAW,CAAC,MAAM;QAChB,IAAI,CAACC,WAAW,CAAC,CAAC,CAACC,KAAK,CAACb,GAAG,IAAI;UAC9Bb,OAAO,CAACc,KAAK,CAAC,GAAG,IAAI,CAACvD,UAAU,0BAA0B,EAAEsD,GAAG,CAAC;QAClE,CAAC,CAAC;MACJ,CAAC,EAAEQ,QAAQ,GAAG,IAAI,CAAC;IACrB;IAEArB,OAAO,CAACuB,IAAI,CACV,GAAG,IAAI,CAAChE,UAAU,2CAA2C,IAAI,CAACN,WAAW,IAC/E,CAAC;EACH,CAAC;EAEDwE,WAAW,GAAG,MAAAA,CAAA,KAAY;IACxB,OAAO,IAAI,CAACnB,YAAY,CAAC,CAAC;EAC5B,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEqB,SAAS,GAAGA,CAACN,QAAQ,EAAEC,gBAAgB,GAAGX,SAAS,KAAK;IACtD,IAAI,CAACS,UAAU,CAACC,QAAQ,EAAEC,gBAAgB,CAAC;EAC7C,CAAC;;EAED;AACF;AACA;AACA;EACEM,OAAO,GAAG,MAAAA,CAAA,KAAY;IACpB,IAAI,IAAI,CAACpF,OAAO,EAAE;MAChB,MAAM,IAAI,CAACqF,aAAa,CAAC,CAAC;IAC5B;IACA5F,OAAO,CAAC6F,IAAI,CAAC,CAAC,CAAC;EACjB,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEnD,gBAAgB,GAAG,MAAMC,gBAAgB,IAAI;IAC3C,IAAI,CAACA,gBAAgB,EAAE;IAEvB,IAAI;MACF,MAAMmD,GAAG,GAAG,GAAG,IAAI,CAACnF,cAAc,UAAU;MAC5C,MAAMoF,GAAG,GAAG,MAAMC,KAAK,CAACF,GAAG,EAAE;QAC3B7D,OAAO,EAAE;UACPC,aAAa,EAAE,SAAS,IAAI,CAACrB,SAAS,EAAE;UACxCoF,MAAM,EAAE;QACV;MACF,CAAC,CAAC;MAEF,IAAI,CAACF,GAAG,CAACG,EAAE,EAAE;QACXnC,OAAO,CAACc,KAAK,CACX,GAAG,IAAI,CAACvD,UAAU,6BAA6ByE,GAAG,CAACI,MAAM,EAC3D,CAAC;QACD;MACF;MAEA,MAAMC,IAAI,GAAG,MAAML,GAAG,CAACK,IAAI,CAAC,CAAC;MAE7B,MAAMC,WAAW,GAAG,yCAAyC;MAC7D,MAAMC,UAAU,GAAG,kBAAkB;MAErC,MAAMC,eAAe,GAAG,IAAIC,GAAG,CAAC,CAAC;MAEjC,IAAIC,KAAK;MACT;MACA,OAAO,CAACA,KAAK,GAAGJ,WAAW,CAACK,IAAI,CAACN,IAAI,CAAC,MAAM,IAAI,EAAE;QAChD,MAAMO,SAAS,GAAGF,KAAK,CAAC,CAAC,CAAC;QAC1B,IAAIG,EAAE;QACN,MAAMC,MAAM,GAAG,CAAC,CAAC;;QAEjB;QACA,OAAO,CAACD,EAAE,GAAGN,UAAU,CAACI,IAAI,CAACC,SAAS,CAAC,MAAM,IAAI,EAAE;UACjD;UACAE,MAAM,CAACD,EAAE,CAAC,CAAC,CAAC,CAAC,GAAGA,EAAE,CAAC,CAAC,CAAC;QACvB;QAEA,IACEC,MAAM,CAACC,GAAG,KAAK,IAAI,CAAC/G,OAAO,IAC3B8G,MAAM,CAAC/E,YAAY,KAAK,IAAI,CAACzB,WAAW,EACxC;UACAkG,eAAe,CAACQ,GAAG,CAAC9B,IAAI,CAACC,SAAS,CAAC2B,MAAM,CAAC,CAAC;QAC7C;MACF;MAEA,IAAIN,eAAe,CAACS,IAAI,KAAK,CAAC,EAAE;QAC9BjD,OAAO,CAACC,GAAG,CACT,GAAG,IAAI,CAAC1C,UAAU,6BAA6B,IAAI,CAACvB,OAAO,EAC7D,CAAC;QACD;MACF;MAEA,MAAMkH,YAAY,GAAG,CAAC,GAAGV,eAAe,CAAC,CACtCW,GAAG,CAACC,CAAC,IAAIlC,IAAI,CAACmC,KAAK,CAACD,CAAC,CAAC,CAAC,CACvBE,MAAM,CACLR,MAAM,IACJA,MAAM,CAACS,QAAQ,IACfT,MAAM,CAACS,QAAQ,KAAK,IAAI,CAACnH,MAAM,IAC/B0G,MAAM,CAAC/E,YAAY,KAAK,IAAI,CAACzB,WACjC,CAAC;MAEH,IAAI4G,YAAY,CAACM,MAAM,KAAK,CAAC,EAAE;QAC7BxD,OAAO,CAACC,GAAG,CAAC,GAAG,IAAI,CAAC1C,UAAU,0BAA0B,CAAC;QACzD;MACF;MAEA,KAAK,MAAMuF,MAAM,IAAII,YAAY,EAAE;QACjC,IAAI;UACF,MAAM,IAAI,CAACrB,aAAa,CAAC;YAAE4B,OAAO,EAAE,IAAI,CAACzH,OAAO;YAAE0H,SAAS,EAAEZ;UAAO,CAAC,CAAC;UACtE9C,OAAO,CAACC,GAAG,CACT,GAAG,IAAI,CAAC1C,UAAU,8BAChBuF,MAAM,CAACS,QAAQ,aACJpE,MAAM,CAACC,IAAI,CAAC0D,MAAM,CAAC,GAClC,CAAC;QACH,CAAC,CAAC,OAAOjC,GAAG,EAAE;UACZb,OAAO,CAACc,KAAK,CACX,GAAG,IAAI,CAACvD,UAAU,iCAAiCuF,MAAM,CAACS,QAAQ,GAAG,EACrE1C,GACF,CAAC;QACH;MACF;MAEAb,OAAO,CAACC,GAAG,CACT,GAAG,IAAI,CAAC1C,UAAU,sCAAsC,IAAI,CAACvB,OAAO,EACtE,CAAC;IACH,CAAC,CAAC,OAAO6E,GAAG,EAAE;MACZb,OAAO,CAACc,KAAK,CAAC,GAAG,IAAI,CAACvD,UAAU,8BAA8B,EAAEsD,GAAG,CAAC;IACtE;EACF,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEgB,aAAa,GAAG,MAAAA,CAAO8B,MAAM,GAAG,CAAC,CAAC,KAAK;IACrC,OAAO,IAAI,CAAC3F,OAAO,CAAC4F,MAAM,CAAC;MACzBH,OAAO,EAAEE,MAAM,CAACF,OAAO,IAAI,IAAI,CAACzH,OAAO;MACvC0H,SAAS,EAAEC,MAAM,CAACD,SAAS,IAAI;QAC7B3F,YAAY,EAAE,IAAI,CAACzB,WAAW;QAC9BiH,QAAQ,EAAE,IAAI,CAACnH;MACjB;IACF,CAAC,CAAC;EACJ,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACE2E,WAAW,GAAG,MAAAA,CAAO4C,MAAM,GAAG,CAAC,CAAC,KAAK;IACnC,IAAI,IAAI,CAACtG,kBAAkB,EAAE;MAC3B,OAAOqD,OAAO,CAACmD,OAAO,CAAC,CAAC;IAC1B;IACA,MAAMH,SAAS,GAAG;MAChB3F,YAAY,EAAE,IAAI,CAACzB,WAAW;MAC9BiH,QAAQ,EAAE,IAAI,CAACnH,MAAM;MACrB,IAAIuH,MAAM,CAACD,SAAS,IAAI,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC1F,OAAO,CAAC8F,IAAI,CAAC;MACvBL,OAAO,EAAEE,MAAM,CAACF,OAAO,IAAI,IAAI,CAACzH,OAAO;MACvC0H;IACF,CAAC,CAAC;EACJ,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;EACEK,iBAAiB,GAAGA,CAACjB,MAAM,GAAG,EAAE,KAAK;IACnC,OAAO,CAAC,GAAG3D,MAAM,CAACC,IAAI,CAAC,IAAI,CAACxB,aAAa,CAAC,EAAE,GAAGkF,MAAM,CAAC;EACxD,CAAC;EAEDkB,gBAAgB,GAAGA,CAAClB,MAAM,GAAG,EAAE,KAAK;IAClC,OAAO,IAAI,CAAClF,aAAa;EAC3B,CAAC;EAEDiB,mBAAmB,GAAGA,CAAA,KAAM;IAC1B5C,OAAO,CAACgI,EAAE,CAAC,QAAQ,EAAE,IAAI,CAACrC,OAAO,CAAC;IAClC3F,OAAO,CAACgI,EAAE,CAAC,SAAS,EAAE,IAAI,CAACrC,OAAO,CAAC;EACrC,CAAC;;EAED;;EAEA,IAAIsC,cAAcA,CAAA,EAAG;IACnB,OAAO,IAAI,CAAC1H,OAAO;EACrB;EAEA,IAAIuD,gBAAgBA,CAAA,EAAG;IACrB,OAAO,IAAI,CAACrD,SAAS;EACvB;EAEA,IAAIyH,QAAQA,CAAA,EAAG;IACb,OAAO,IAAI,CAAC3G,SAAS;EACvB;EAEA,MAAM4G,kBAAkBA,CAAA,EAAG;IACzB,OAAO,IAAI,CAAC5G,SAAS,CAACwD,OAAO,CAAC,CAAC;EACjC;EAEAqD,iBAAiBA,CAAA,EAAG;IAClB,OAAO,OAAOC,GAAG,EAAEtC,GAAG,KAAK;MACzB,IAAI;QACF,MAAMhB,OAAO,GAAG,MAAM,IAAI,CAACoD,kBAAkB,CAAC,CAAC;QAC/CpC,GAAG,CAACpB,GAAG,CAAC,cAAc,EAAElF,MAAM,CAACiC,QAAQ,CAAC4G,WAAW,CAAC;QACpDvC,GAAG,CAACwC,GAAG,CAACxD,OAAO,CAAC;MAClB,CAAC,CAAC,OAAOH,GAAG,EAAE;QACZb,OAAO,CAACc,KAAK,CAAC,GAAG,IAAI,CAACvD,UAAU,yBAAyB,EAAEsD,GAAG,CAAC;QAC/DmB,GAAG,CAACI,MAAM,CAAC,GAAG,CAAC,CAACoC,GAAG,CAAC,2BAA2B,CAAC;MAClD;IACF,CAAC;EACH;AACF;AAEAC,MAAM,CAACC,OAAO,GAAG;EAAE7I;AAAkB,CAAC","ignoreList":[]}
@@ -4,6 +4,31 @@
4
4
  * Extends BaseMetricsClient for common functionality.
5
5
  */
6
6
  export class MetricsClient extends BaseMetricsClient {
7
+ /**
8
+ * @param {Object} config
9
+ * @param {string} [config.appName] Name of the application
10
+ * @param {string} [config.dynoId] Dyno/instance ID
11
+ * @param {string} [config.processType] Process type (web, worker, etc.)
12
+ * @param {boolean} [config.enabled] Enable metrics collection
13
+ * @param {boolean} [config.logValues] Log metrics values to console
14
+ * @param {string} [config.pushgatewayUrl] PushGateway URL
15
+ * @param {string} [config.pushgatewaySecret] PushGateway secret token
16
+ * @param {number} [config.intervalSec] Interval in seconds for pushing metrics
17
+ * @param {boolean} [config.removeOldMetrics] Enable to clear metrics by service name
18
+ * @param {function} [config.startupValidation] Add to validate on start push.
19
+ */
20
+ constructor(config?: {
21
+ appName?: string | undefined;
22
+ dynoId?: string | undefined;
23
+ processType?: string | undefined;
24
+ enabled?: boolean | undefined;
25
+ logValues?: boolean | undefined;
26
+ pushgatewayUrl?: string | undefined;
27
+ pushgatewaySecret?: string | undefined;
28
+ intervalSec?: number | undefined;
29
+ removeOldMetrics?: boolean | undefined;
30
+ startupValidation?: Function | undefined;
31
+ });
7
32
  _lastUsageMicros: number;
8
33
  _lastCheckTime: number;
9
34
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"metricsClient.d.ts","sourceRoot":"","sources":["../../src/metrics/metricsClient.js"],"names":[],"mappings":"AAIA;;;;GAIG;AACH;IAiBI,yBAAyB;IACzB,uBAAgC;IAKlC;;;OAGG;IACH,4BA4DC;IAED;;;OAGG;IACH,0BAFa,MAAM,CA2BlB;IAED;;;OAGG;IACH,oBAFa,MAAM,CAiBlB;IAED;;;OAGG;IACH,2BAFa,MAAM,CAWlB;IAED;;;OAGG;IACH,2BAFa,MAAM,CAgBlB;IAED;;;OAGG;IACH,cAFa,QAAQ,MAAM,CAAC,CAO3B;IAED;;;;;;;;;;OAUG;IACH;QAP0B,MAAM,EAArB,MAAM;QACS,KAAK,EAApB,MAAM;QACS,WAAW,EAA1B,MAAM;QACU,KAAK;QACL,UAAU;QACX,QAAQ,EAAvB,MAAM;aA2BhB;IAED;;;OAGG;IACH,oEA+BC;CACF"}
1
+ {"version":3,"file":"metricsClient.d.ts","sourceRoot":"","sources":["../../src/metrics/metricsClient.js"],"names":[],"mappings":"AAIA;;;;GAIG;AACH;IACE;;;;;;;;;;;;OAYG;IACH;QAX2B,OAAO;QACP,MAAM;QACN,WAAW;QACV,OAAO;QACP,SAAS;QACV,cAAc;QACd,iBAAiB;QACjB,WAAW;QACV,gBAAgB;QACf,iBAAiB;OAS7C;IAJC,yBAAyB;IACzB,uBAAgC;IAKlC;;;OAGG;IACH,4BA4DC;IAED;;;OAGG;IACH,0BAFa,MAAM,CA2BlB;IAED;;;OAGG;IACH,oBAFa,MAAM,CAiBlB;IAED;;;OAGG;IACH,2BAFa,MAAM,CAWlB;IAED;;;OAGG;IACH,2BAFa,MAAM,CAgBlB;IAED;;;OAGG;IACH,cAFa,QAAQ,MAAM,CAAC,CAO3B;IAED;;;;;;;;;;OAUG;IACH;QAP0B,MAAM,EAArB,MAAM;QACS,KAAK,EAApB,MAAM;QACS,WAAW,EAA1B,MAAM;QACU,KAAK;QACL,UAAU;QACX,QAAQ,EAAvB,MAAM;aA2BhB;IAED;;;OAGG;IACH,oEA+BC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adalo/metrics",
3
- "version": "0.1.128",
3
+ "version": "0.1.129",
4
4
  "description": "Reusable metrics utilities for Node.js and Laravel apps",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -18,6 +18,7 @@ class BaseMetricsClient {
18
18
  * @param {number} [config.intervalSec] Interval in seconds for pushing metrics
19
19
  * @param {boolean} [config.removeOldMetrics] Enable to clear metrics by service name
20
20
  * @param {function} [config.startupValidation] Add to validate on start push.
21
+ * @param {boolean} [config.disablePushgateway] Disable pushing to Pushgateway (use HTTP scraping instead)
21
22
  */
22
23
  constructor(config = {}) {
23
24
  this.appName = config.appName || process.env.BUILD_APP_NAME || 'unknown-app'
@@ -38,6 +39,9 @@ class BaseMetricsClient {
38
39
  parseInt(process.env.METRICS_INTERVAL_SEC || '', 10) ||
39
40
  15
40
41
  this.startupValidation = config.startupValidation
42
+ this.disablePushgateway =
43
+ config.disablePushgateway ??
44
+ process.env.METRICS_DISABLE_PUSHGATEWAY === 'true'
41
45
 
42
46
  this.prefixLogs = `[${this.processType}] [${this.appName}] [${this.dynoId}] [Monitoring]`
43
47
 
@@ -152,7 +156,7 @@ class BaseMetricsClient {
152
156
  for (const [name, updateFn] of Object.entries(this.gaugeUpdaters)) {
153
157
  try {
154
158
  if (!updateFn) {
155
- return
159
+ continue
156
160
  }
157
161
  const result = updateFn()
158
162
  const val = result instanceof Promise ? await result : result
@@ -165,7 +169,9 @@ class BaseMetricsClient {
165
169
  }
166
170
  }
167
171
 
168
- await this.gatewayPush()
172
+ if (!this.disablePushgateway) {
173
+ await this.gatewayPush()
174
+ }
169
175
  // this.clearAllCounters() //TODO: or uncommit or delete (based on grafana expectation)
170
176
 
171
177
  if (this.logValues) {
@@ -365,6 +371,9 @@ class BaseMetricsClient {
365
371
  * @returns {Promise<void>}
366
372
  */
367
373
  gatewayPush = async (params = {}) => {
374
+ if (this.disablePushgateway) {
375
+ return Promise.resolve()
376
+ }
368
377
  const groupings = {
369
378
  process_type: this.processType,
370
379
  instance: this.dynoId,
@@ -409,6 +418,23 @@ class BaseMetricsClient {
409
418
  get registry() {
410
419
  return this._registry
411
420
  }
421
+
422
+ async getMetricsAsString() {
423
+ return this._registry.metrics()
424
+ }
425
+
426
+ metricsMiddleware() {
427
+ return async (req, res) => {
428
+ try {
429
+ const metrics = await this.getMetricsAsString()
430
+ res.set('Content-Type', client.register.contentType)
431
+ res.end(metrics)
432
+ } catch (err) {
433
+ console.error(`${this.prefixLogs} Failed to get metrics:`, err)
434
+ res.status(500).end('Failed to collect metrics')
435
+ }
436
+ }
437
+ }
412
438
  }
413
439
 
414
440
  module.exports = { BaseMetricsClient }