@adalo/metrics 0.0.0-staging.12 → 0.0.0-staging.14
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.
- package/README.md +19 -11
- package/lib/metrics/baseMetricsClient.d.ts +2 -1
- package/lib/metrics/baseMetricsClient.d.ts.map +1 -1
- package/lib/metrics/baseMetricsClient.js +4 -2
- package/lib/metrics/baseMetricsClient.js.map +1 -1
- package/lib/metrics/metricsClient.d.ts +37 -3
- package/lib/metrics/metricsClient.d.ts.map +1 -1
- package/lib/metrics/metricsClient.js +26 -4
- package/lib/metrics/metricsClient.js.map +1 -1
- package/package.json +1 -1
- package/src/metrics/baseMetricsClient.js +2 -1
- package/src/metrics/metricsClient.js +24 -3
package/README.md
CHANGED
|
@@ -24,19 +24,27 @@ yarn add redis@3
|
|
|
24
24
|
|
|
25
25
|
Without it, the client logs a warning and keeps per-process HTTP counters only. Queue/health code can keep using **ioredis** or node-redis v4 via injected clients; the optional peer is only for the HTTP metrics Redis store’s `createClient` API.
|
|
26
26
|
|
|
27
|
-
## Constructor
|
|
27
|
+
## Constructor (`MetricsClient`)
|
|
28
|
+
|
|
29
|
+
All fields are optional; defaults come from environment variables where noted.
|
|
30
|
+
|
|
31
|
+
| Field | Purpose |
|
|
32
|
+
|-------|---------|
|
|
33
|
+
| `appName`, `dynoId`, `processType` | Label `app`, `dyno_id`, `process_type`. Use `processType: 'metrics'` for the Procfile **`metrics:`** worker (metrics-exporter) so HTTP Redis drain + push behaves correctly with `DYNO=metrics.*` or `BUILD_DYNO_PROCESS_TYPE=metrics`. |
|
|
34
|
+
| `enabled`, `logValues`, `pushgatewayUrl`, `pushgatewaySecret`, `intervalSec`, `removeOldMetrics`, `startupValidation`, `disablePushgateway`, `includeNodeDefaultMetrics` | Same as base client (push to VM-agent, interval, etc.). |
|
|
35
|
+
| `httpMetricsEnabled`, `httpMetricsRedisUrl`, `httpMetricsRedisAggregation` | HTTP counters / Redis aggregation (multi-dyno Redis HTTP). |
|
|
36
|
+
|
|
37
|
+
**`startPush(interval?, customPushMetrics?)`** — both arguments are optional. With no args, the interval is `intervalSec` from config / `METRICS_INTERVAL_SEC` (default 15s).
|
|
38
|
+
|
|
39
|
+
### Metrics exporter entrypoint
|
|
40
|
+
|
|
28
41
|
```ts
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
enabled, // defaults: process.env.METRICS_ENABLED === 'true'
|
|
34
|
-
logValues, // defaults: process.env.METRICS_LOG_VALUES === 'true'
|
|
35
|
-
pushgatewayUrl, // defaults: process.env.METRICS_PUSHGATEWAY_URL || ''
|
|
36
|
-
pushgatewaySecret, // defaults: process.env.METRICS_PUSHGATEWAY_SECRET || '' (Base64 of user:password)
|
|
37
|
-
intervalSec, // defaults: process.env.METRICS_INTERVAL_SEC || 15
|
|
38
|
-
})
|
|
42
|
+
import { MetricsClient } from '@adalo/metrics'
|
|
43
|
+
|
|
44
|
+
const client = new MetricsClient({ processType: 'metrics' })
|
|
45
|
+
client.startPush()
|
|
39
46
|
```
|
|
47
|
+
|
|
40
48
|
## Example Usage
|
|
41
49
|
```ts
|
|
42
50
|
import { MetricsClient } from '@adalo/metrics-js'
|
|
@@ -110,7 +110,8 @@ export class BaseMetricsClient {
|
|
|
110
110
|
_pushMetrics: () => Promise<void>;
|
|
111
111
|
_startPush: (interval?: number, customPushMetics?: undefined) => void;
|
|
112
112
|
_idleInterval: NodeJS.Timer | null | undefined;
|
|
113
|
-
|
|
113
|
+
/** Must be a prototype method (not a class field) so subclasses can `super.pushMetrics()`. */
|
|
114
|
+
pushMetrics(): Promise<void>;
|
|
114
115
|
/**
|
|
115
116
|
* Start periodic metrics collection and push.
|
|
116
117
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseMetricsClient.d.ts","sourceRoot":"","sources":["../../src/metrics/baseMetricsClient.js"],"names":[],"mappings":"AAKA;;;;GAIG;AACH;IACE;;;;;;;;;;;;;;OAcG;IACH;QAb2B,OAAO;QACP,MAAM;QACN,WAAW;QACV,OAAO;QACP,SAAS;QACV,cAAc;QACd,iBAAiB;QACjB,WAAW;QACV,gBAAgB;QACf,iBAAiB;QAClB,kBAAkB;QAClB,yBAAyB;OA8DpD;IA3DC,gBAA4E;IAC5E,eAAqE;IACrE,oBAG6B;IAC7B,mCAC4C;IAC5C,iBAAuE;IACvE,mBAC+D;IAC/D,uBACoE;IACpE,kBAC0E;IAC1E,oBAGI;IACJ,wCAAiD;IACjD,4BAEoD;IACpD,0BAEmD;IAEnD,mBAAyF;IAEzF,uEAAsC;IAKtC;;;;MAIC;IAED,oFAAoF;IACpF;;;MAGC;IAGD,aAAmB;IACnB,WAAgB;IAChB,aAAkB;IAClB,sBAA2B;IAE3B,mEAAmE;IACnE;YADkB,MAAM,SAAc,MAAM,GAAG,QAAQ,MAAM,CAAC;MACvC;IAKvB,sCAAwC;IAG1C;;;;;;;;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;;;;;;;;;;;;OAYG;IACH;QAT0B,IAAI,EAAnB,MAAM;QACS,IAAI,EAAnB,MAAM;QACY,UAAU;QACX,sBAAsB;kBAE3B,MAAM,mBAAmB,MAAM,KAAK,IAAI,CAgC9D;IAED;;OAEG;IACH,6BAKC;IAED;;OAEG;IACH,kCAiCC;IAED,sEAmDC;IA/CK,+CAA0D;IAiDhE,
|
|
1
|
+
{"version":3,"file":"baseMetricsClient.d.ts","sourceRoot":"","sources":["../../src/metrics/baseMetricsClient.js"],"names":[],"mappings":"AAKA;;;;GAIG;AACH;IACE;;;;;;;;;;;;;;OAcG;IACH;QAb2B,OAAO;QACP,MAAM;QACN,WAAW;QACV,OAAO;QACP,SAAS;QACV,cAAc;QACd,iBAAiB;QACjB,WAAW;QACV,gBAAgB;QACf,iBAAiB;QAClB,kBAAkB;QAClB,yBAAyB;OA8DpD;IA3DC,gBAA4E;IAC5E,eAAqE;IACrE,oBAG6B;IAC7B,mCAC4C;IAC5C,iBAAuE;IACvE,mBAC+D;IAC/D,uBACoE;IACpE,kBAC0E;IAC1E,oBAGI;IACJ,wCAAiD;IACjD,4BAEoD;IACpD,0BAEmD;IAEnD,mBAAyF;IAEzF,uEAAsC;IAKtC;;;;MAIC;IAED,oFAAoF;IACpF;;;MAGC;IAGD,aAAmB;IACnB,WAAgB;IAChB,aAAkB;IAClB,sBAA2B;IAE3B,mEAAmE;IACnE;YADkB,MAAM,SAAc,MAAM,GAAG,QAAQ,MAAM,CAAC;MACvC;IAKvB,sCAAwC;IAG1C;;;;;;;;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;;;;;;;;;;;;OAYG;IACH;QAT0B,IAAI,EAAnB,MAAM;QACS,IAAI,EAAnB,MAAM;QACY,UAAU;QACX,sBAAsB;kBAE3B,MAAM,mBAAmB,MAAM,KAAK,IAAI,CAgC9D;IAED;;OAEG;IACH,6BAKC;IAED;;OAEG;IACH,kCAiCC;IAED,sEAmDC;IA/CK,+CAA0D;IAiDhE,8FAA8F;IAC9F,6BAEC;IAED;;;;;;;;;OASG;IACH,iFAEC;IAED;;;OAGG;IACH,eAFa,QAAQ,IAAI,CAAC,CAOzB;IAED;;;;;;;;;OASG;IACH,yBAEC;IAED;;;OAGG;IACH,qBAFa,QAAQ,IAAI,CAAC,CAezB;IAED;;;OAGG;IACH,8BAkDC;IAED;;;;;OAKG;IACH,8CAFa,QAAQ,IAAI,CAAC,CAgBzB;IAED;;;OAGG;IACH,uBAoDC;IAED;;;;;;OAMG;IACH,6BAHW,MAAM,EAAE,KACN,MAAM,EAAE,CAIpB;IAED;;;;;;OAMG;IACH,0CAHW,MAAM,EAAE,KACN,MAAM,EAAE,CAIpB;IAED;;;;MAEC;IAED,gCAGC;IAID,8BAEC;IAED,gCAEC;IAED,4EAEC;IAED,sCAEC;IAED,2DAWC;CACF"}
|
|
@@ -227,9 +227,11 @@ class BaseMetricsClient {
|
|
|
227
227
|
}
|
|
228
228
|
console.warn(`${this.prefixLogs} Metrics collection started. (interval: ${this.intervalSec}s, push: ${pushOrigin})`);
|
|
229
229
|
};
|
|
230
|
-
|
|
230
|
+
|
|
231
|
+
/** Must be a prototype method (not a class field) so subclasses can `super.pushMetrics()`. */
|
|
232
|
+
async pushMetrics() {
|
|
231
233
|
return this._pushMetrics();
|
|
232
|
-
}
|
|
234
|
+
}
|
|
233
235
|
|
|
234
236
|
/**
|
|
235
237
|
* Start periodic metrics collection and push.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseMetricsClient.js","names":["client","require","https","http","URL","BaseMetricsClient","constructor","config","appName","process","env","BUILD_APP_NAME","dynoId","HOSTNAME","processType","BUILD_DYNO_PROCESS_TYPE","includeNodeDefaultMetrics","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","removeOldMetrics","METRICS_REMOVE_OLD_METRICS","prefixLogs","_registry","Registry","collectDefaultMetrics","register","defaultLabels","app","dyno_id","process_type","defaultLabelsWithoutDynoId","gateway","gauges","counters","countersFunctions","gaugeUpdaters","_clearOldWorkers","_setCleanupHandlers","keepProcessAliveWhenDisabled","createGauge","name","help","updateFn","labelNames","Object","keys","g","Gauge","registers","createCounter","useLabelsWithoutDynoId","defaultSet","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","_idleInterval","setInterval","clearInterval","runPush","resolve","pushMetrics","catch","pushOrigin","trim","origin","startPush","cleanup","gatewayDelete","exit","_deleteFromVMByLabels","message","esc","s","String","replace","selector","u","reject","Error","path","encodeURIComponent","req","protocol","request","hostname","port","method","headers","Authorization","agent","Agent","keepAlive","res","statusCode","on","chunk","end","params","_pushToVMAgent","pushUrl","pathname","search","contentType","then","setHeader","Buffer","byteLength","withDefaultLabels","labels","withDefaultLabelsWithoutDynoId","getDefaultLabels","metricsEnabled","registry","getMetricsAsString","metricsMiddleware","status","module","exports"],"sources":["../../src/metrics/baseMetricsClient.js"],"sourcesContent":["const client = require('prom-client')\nconst https = require('https')\nconst http = require('http')\nconst { URL } = require('url')\n\n/**\n * BaseMetricsClient provides common functionality for all metrics clients.\n * Handles registry setup, push to remote (VM-agent), default labels, and common operations.\n * Always pushes registry to the configured URL (POST Prometheus text format + Basic auth). No Pushgateway.\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] Push URL (VM-agent import endpoint, e.g. .../api/v1/import/prometheus). /metrics is for GET (scrape), not POST (push).\n * @param {string} [config.pushgatewaySecret] Basic auth secret (Base64 of user:password)\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 * @param {boolean} [config.includeNodeDefaultMetrics] Register prom-client default process metrics (heap, etc.); defaults true unless MetricsClient forces false for web+Redis HTTP recording dynos.\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.includeNodeDefaultMetrics =\n config.includeNodeDefaultMetrics !== false\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 this.removeOldMetrics =\n config.removeOldMetrics ??\n process.env.METRICS_REMOVE_OLD_METRICS === 'true'\n\n this.prefixLogs = `[${this.processType}] [${this.appName}] [${this.dynoId}] [Monitoring]`\n\n this._registry = new client.Registry()\n if (this.includeNodeDefaultMetrics) {\n client.collectDefaultMetrics({ register: this._registry })\n }\n\n this.defaultLabels = {\n app: this.appName,\n dyno_id: this.dynoId,\n process_type: this.processType,\n }\n\n /** Default labels without dyno_id (for HTTP metrics so dyno_id is not included). */\n this.defaultLabelsWithoutDynoId = {\n app: this.appName,\n process_type: this.processType,\n }\n\n // Always push to configured URL (VM-agent). No Pushgateway.\n this.gateway = null\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 this.keepProcessAliveWhenDisabled = true\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 * @param {boolean} [params.useLabelsWithoutDynoId=false] - If true, counter uses app/process_type only (no dyno_id). Use for HTTP metrics.\n *\n * @returns {(labels?: Object, incrementValue?: number) => void}\n * A function to increment the counter.\n * Usage: (labels?, incrementValue?)\n */\n createCounter({\n name,\n help,\n labelNames = Object.keys(this.defaultLabels),\n useLabelsWithoutDynoId = false,\n }) {\n if (this.counters[name]) return this.countersFunctions[name]\n\n const defaultSet = useLabelsWithoutDynoId\n ? this.defaultLabelsWithoutDynoId\n : this.defaultLabels\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({ ...defaultSet, ...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 if (this.keepProcessAliveWhenDisabled && !this._idleInterval) {\n this._idleInterval = setInterval(() => {}, 60 * 60 * 1000)\n }\n return\n }\n\n if (this._idleInterval) {\n clearInterval(this._idleInterval)\n this._idleInterval = null\n }\n\n if (this.startupValidation && !this.startupValidation()) {\n return\n }\n\n const runPush = () => {\n if (customPushMetics && typeof customPushMetics === 'function') {\n return Promise.resolve(customPushMetics())\n }\n return this.pushMetrics()\n }\n\n if (customPushMetics && typeof customPushMetics === 'function') {\n setInterval(() => customPushMetics(), interval * 1000)\n } else {\n setInterval(() => {\n runPush().catch(err => {\n console.error(`${this.prefixLogs} Failed to push metrics:`, err)\n })\n }, interval * 1000)\n }\n\n // First push immediately so metrics appear without waiting for the first interval\n runPush().catch(err => {\n console.error(`${this.prefixLogs} Failed to push metrics (initial):`, err)\n })\n\n let pushOrigin = 'none'\n try {\n if (this.pushgatewayUrl && this.pushgatewayUrl.trim()) {\n pushOrigin = new URL(this.pushgatewayUrl.trim()).origin\n }\n } catch {\n pushOrigin = 'invalid URL'\n }\n console.warn(\n `${this.prefixLogs} Metrics collection started. (interval: ${this.intervalSec}s, push: ${pushOrigin})`\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 // No Pushgateway; VM-agent does not support per-instance delete. Skip.\n }\n\n /**\n * On shutdown: optionally delete this instance's metrics from VictoriaMetrics (by app, dyno_id, process_type).\n * @returns {Promise<void>}\n */\n gatewayDelete = async () => {\n if (\n this.removeOldMetrics &&\n this.pushgatewayUrl &&\n this.pushgatewayUrl.trim()\n ) {\n await this._deleteFromVMByLabels().catch(err => {\n console.warn(\n `${this.prefixLogs} Deletion from VM on shutdown failed:`,\n err.message\n )\n })\n }\n }\n\n /**\n * Call VictoriaMetrics delete_series API to remove all series matching this instance's labels (app, dyno_id, process_type).\n * @private\n */\n _deleteFromVMByLabels = () => {\n const esc = s => String(s).replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n const selector = `{app=\"${esc(this.appName)}\",dyno_id=\"${esc(\n this.dynoId\n )}\",process_type=\"${esc(this.processType)}\"}`\n let origin\n try {\n const u = new URL((this.pushgatewayUrl || '').trim())\n origin = u.origin\n } catch {\n return Promise.reject(new Error('Invalid push URL'))\n }\n const path = `/api/v1/admin/tsdb/delete_series?match[]=${encodeURIComponent(\n selector\n )}`\n return new Promise((resolve, reject) => {\n const u = new URL(origin)\n const req = (u.protocol === 'https:' ? https : http).request(\n {\n hostname: u.hostname,\n port: u.port || (u.protocol === 'https:' ? 443 : 80),\n path,\n method: 'POST',\n headers: {\n 'Content-Length': '0',\n Authorization: this.authToken\n ? `Basic ${this.authToken}`\n : undefined,\n },\n agent:\n u.protocol === 'https:'\n ? new https.Agent({ keepAlive: false })\n : undefined,\n },\n res => {\n if (res.statusCode >= 200 && res.statusCode < 300) resolve()\n else {\n let data = ''\n res.on('data', chunk => {\n data += chunk\n })\n res.on('end', () =>\n reject(new Error(`Delete failed: ${res.statusCode} ${data}`))\n )\n }\n }\n )\n req.on('error', reject)\n req.end()\n })\n }\n\n /**\n * Push registry to configured URL (VM-agent). POST Prometheus text format + Basic auth.\n *\n * @param {object} [params] Unused; kept for API compatibility.\n * @returns {Promise<void>}\n */\n gatewayPush = async (params = {}) => {\n if (this.disablePushgateway) {\n console.warn(\n `${this.prefixLogs} Metrics push skipped: METRICS_DISABLE_PUSHGATEWAY is set`\n )\n return Promise.resolve()\n }\n if (!this.pushgatewayUrl || !this.pushgatewayUrl.trim()) {\n console.warn(\n `${this.prefixLogs} Metrics push skipped: METRICS_PUSHGATEWAY_URL is not set`\n )\n return Promise.resolve()\n }\n return this._pushToVMAgent()\n }\n\n /**\n * POST registry (Prometheus text format) to VM-agent. VM-agent accepts push at /api/v1/import/prometheus; /metrics is GET (scrape) only.\n * @private\n */\n _pushToVMAgent = () => {\n let pushUrl = (this.pushgatewayUrl || '').trim()\n try {\n const u = new URL(pushUrl)\n if (!u.pathname || u.pathname === '/' || u.pathname === '/metrics') {\n pushUrl = `${u.origin}/api/v1/import/prometheus${u.search}`\n }\n } catch {\n // leave pushUrl as-is\n }\n return new Promise((resolve, reject) => {\n const u = new URL(pushUrl)\n const req = (u.protocol === 'https:' ? https : http).request(\n {\n hostname: u.hostname,\n port: u.port || (u.protocol === 'https:' ? 443 : 80),\n path: u.pathname + u.search,\n method: 'POST',\n headers: {\n 'Content-Type': client.register.contentType,\n Authorization: this.authToken\n ? `Basic ${this.authToken}`\n : undefined,\n },\n agent:\n u.protocol === 'https:'\n ? new https.Agent({ keepAlive: true })\n : undefined,\n },\n res => {\n if (res.statusCode >= 200 && res.statusCode < 300) {\n resolve()\n } else {\n let data = ''\n res.on('data', chunk => {\n data += chunk\n })\n res.on('end', () =>\n reject(new Error(`Push failed: ${res.statusCode} ${data}`))\n )\n }\n }\n )\n req.on('error', reject)\n this._registry\n .metrics()\n .then(metrics => {\n req.setHeader('Content-Length', Buffer.byteLength(metrics, 'utf8'))\n req.end(metrics, 'utf8')\n })\n .catch(reject)\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 /**\n * Merge default labels without dyno_id (`app`, `process_type`) with custom label names.\n * Use for HTTP metrics so dyno_id is not included.\n *\n * @param {string[]} labels Additional label names\n * @returns {string[]} Combined label names\n */\n withDefaultLabelsWithoutDynoId = (labels = []) => {\n return [...Object.keys(this.defaultLabelsWithoutDynoId), ...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;AAC9B,MAAME,IAAI,GAAGF,OAAO,CAAC,MAAM,CAAC;AAC5B,MAAM;EAAEG;AAAI,CAAC,GAAGH,OAAO,CAAC,KAAK,CAAC;;AAE9B;AACA;AACA;AACA;AACA;AACA,MAAMI,iBAAiB,CAAC;EACtB;AACF;AACA;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,yBAAyB,GAC5BT,MAAM,CAACS,yBAAyB,KAAK,KAAK;IAC5C,IAAI,CAACC,OAAO,GAAGV,MAAM,CAACU,OAAO,IAAIR,OAAO,CAACC,GAAG,CAACQ,eAAe,KAAK,MAAM;IACvE,IAAI,CAACC,SAAS,GACZZ,MAAM,CAACY,SAAS,IAAIV,OAAO,CAACC,GAAG,CAACU,kBAAkB,KAAK,MAAM;IAC/D,IAAI,CAACC,cAAc,GACjBd,MAAM,CAACc,cAAc,IAAIZ,OAAO,CAACC,GAAG,CAACY,uBAAuB,IAAI,EAAE;IACpE,IAAI,CAACC,SAAS,GACZhB,MAAM,CAACiB,iBAAiB,IAAIf,OAAO,CAACC,GAAG,CAACe,0BAA0B,IAAI,EAAE;IAC1E,IAAI,CAACC,WAAW,GACdnB,MAAM,CAACmB,WAAW,IAClBC,QAAQ,CAAClB,OAAO,CAACC,GAAG,CAACkB,oBAAoB,IAAI,EAAE,EAAE,EAAE,CAAC,IACpD,EAAE;IACJ,IAAI,CAACC,iBAAiB,GAAGtB,MAAM,CAACsB,iBAAiB;IACjD,IAAI,CAACC,kBAAkB,GACrBvB,MAAM,CAACuB,kBAAkB,IACzBrB,OAAO,CAACC,GAAG,CAACqB,2BAA2B,KAAK,MAAM;IACpD,IAAI,CAACC,gBAAgB,GACnBzB,MAAM,CAACyB,gBAAgB,IACvBvB,OAAO,CAACC,GAAG,CAACuB,0BAA0B,KAAK,MAAM;IAEnD,IAAI,CAACC,UAAU,GAAG,IAAI,IAAI,CAACpB,WAAW,MAAM,IAAI,CAACN,OAAO,MAAM,IAAI,CAACI,MAAM,gBAAgB;IAEzF,IAAI,CAACuB,SAAS,GAAG,IAAInC,MAAM,CAACoC,QAAQ,CAAC,CAAC;IACtC,IAAI,IAAI,CAACpB,yBAAyB,EAAE;MAClChB,MAAM,CAACqC,qBAAqB,CAAC;QAAEC,QAAQ,EAAE,IAAI,CAACH;MAAU,CAAC,CAAC;IAC5D;IAEA,IAAI,CAACI,aAAa,GAAG;MACnBC,GAAG,EAAE,IAAI,CAAChC,OAAO;MACjBiC,OAAO,EAAE,IAAI,CAAC7B,MAAM;MACpB8B,YAAY,EAAE,IAAI,CAAC5B;IACrB,CAAC;;IAED;IACA,IAAI,CAAC6B,0BAA0B,GAAG;MAChCH,GAAG,EAAE,IAAI,CAAChC,OAAO;MACjBkC,YAAY,EAAE,IAAI,CAAC5B;IACrB,CAAC;;IAED;IACA,IAAI,CAAC8B,OAAO,GAAG,IAAI;IACnB,IAAI,CAACC,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,CAAC1C,MAAM,CAACyB,gBAAgB,CAAC;IAC9C,IAAI,CAACkB,mBAAmB,CAAC,CAAC;IAE1B,IAAI,CAACC,4BAA4B,GAAG,IAAI;EAC1C;;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,CAACnB,aAAa;EAC7C,CAAC,KAAK;IACJ,IAAI,IAAI,CAACM,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,CAAC1B,SAAS;IAC5B,CAAC,CAAC;IACF,IAAI,CAACU,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;AACA;EACEG,aAAaA,CAAC;IACZT,IAAI;IACJC,IAAI;IACJE,UAAU,GAAGC,MAAM,CAACC,IAAI,CAAC,IAAI,CAACnB,aAAa,CAAC;IAC5CwB,sBAAsB,GAAG;EAC3B,CAAC,EAAE;IACD,IAAI,IAAI,CAACjB,QAAQ,CAACO,IAAI,CAAC,EAAE,OAAO,IAAI,CAACN,iBAAiB,CAACM,IAAI,CAAC;IAE5D,MAAMW,UAAU,GAAGD,sBAAsB,GACrC,IAAI,CAACpB,0BAA0B,GAC/B,IAAI,CAACJ,aAAa;IAEtB,MAAM0B,CAAC,GAAG,IAAIjE,MAAM,CAACkE,OAAO,CAAC;MAC3Bb,IAAI;MACJC,IAAI;MACJE,UAAU;MACVK,SAAS,EAAE,CAAC,IAAI,CAAC1B,SAAS;IAC5B,CAAC,CAAC;IACF,IAAI,CAACW,QAAQ,CAACO,IAAI,CAAC,GAAGY,CAAC;IAEvB,IAAI,CAAClB,iBAAiB,GAAG;MACvB,GAAG,IAAI,CAACA,iBAAiB;MACzB,CAACM,IAAI,GAAG,CAACc,IAAI,GAAG,CAAC,CAAC,EAAEC,KAAK,GAAG,CAAC,KAAK;QAChCH,CAAC,CAACI,GAAG,CAAC;UAAE,GAAGL,UAAU;UAAE,GAAGG;QAAK,CAAC,EAAEC,KAAK,CAAC;MAC1C;IACF,CAAC;IAED,OAAO,IAAI,CAACrB,iBAAiB,CAACM,IAAI,CAAC;EACrC;;EAEA;AACF;AACA;EACEiB,gBAAgB,GAAGA,CAAA,KAAM;IACvB,IAAI,IAAI,CAACC,gBAAgB,EAAE;MACzBC,OAAO,CAACC,GAAG,CAAC,qBAAqB,EAAEhB,MAAM,CAACC,IAAI,CAAC,IAAI,CAACZ,QAAQ,CAAC,CAAC;IAChE;IACAW,MAAM,CAACiB,MAAM,CAAC,IAAI,CAAC5B,QAAQ,CAAC,CAAC6B,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,CAACzB,IAAI,EAAEE,QAAQ,CAAC,IAAIE,MAAM,CAACsB,OAAO,CAAC,IAAI,CAAC/B,aAAa,CAAC,EAAE;QACjE,IAAI;UACF,IAAI,CAACO,QAAQ,EAAE;YACb;UACF;UACA,MAAMyB,MAAM,GAAGzB,QAAQ,CAAC,CAAC;UACzB,MAAM0B,GAAG,GAAGD,MAAM,YAAYE,OAAO,GAAG,MAAMF,MAAM,GAAGA,MAAM;UAC7D,IAAIC,GAAG,KAAKE,SAAS,EAAE,IAAI,CAACtC,MAAM,CAACQ,IAAI,CAAC,CAAC+B,GAAG,CAAC,IAAI,CAAC7C,aAAa,EAAE0C,GAAG,CAAC;QACvE,CAAC,CAAC,OAAOI,GAAG,EAAE;UACZb,OAAO,CAACc,KAAK,CACX,GAAG,IAAI,CAACpD,UAAU,2BAA2BmB,IAAI,GAAG,EACpDgC,GACF,CAAC;QACH;MACF;MAEA,IAAI,CAAC,IAAI,CAACvD,kBAAkB,EAAE;QAC5B,MAAM,IAAI,CAACyD,WAAW,CAAC,CAAC;MAC1B;MACA;;MAEA,IAAI,IAAI,CAACpE,SAAS,EAAE;QAClB,MAAMqE,OAAO,GAAG,MAAM,IAAI,CAACrD,SAAS,CAACsD,gBAAgB,CAAC,CAAC;QACvDjB,OAAO,CAACC,GAAG,CACT,GAAG,IAAI,CAACvC,UAAU,aAAa,EAC/BwD,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,CAACpD,UAAU,0BAA0B,EAAEmD,GAAG,CAAC;IAClE;EACF,CAAC;EAEDO,UAAU,GAAGA,CAACC,QAAQ,GAAG,IAAI,CAACnE,WAAW,EAAEoE,gBAAgB,GAAGX,SAAS,KAAK;IAC1E,IAAI,CAAC,IAAI,CAAClE,OAAO,EAAE;MACjBuD,OAAO,CAACuB,IAAI,CAAC,GAAG,IAAI,CAAC7D,UAAU,mBAAmB,CAAC;MACnD,IAAI,IAAI,CAACiB,4BAA4B,IAAI,CAAC,IAAI,CAAC6C,aAAa,EAAE;QAC5D,IAAI,CAACA,aAAa,GAAGC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;MAC5D;MACA;IACF;IAEA,IAAI,IAAI,CAACD,aAAa,EAAE;MACtBE,aAAa,CAAC,IAAI,CAACF,aAAa,CAAC;MACjC,IAAI,CAACA,aAAa,GAAG,IAAI;IAC3B;IAEA,IAAI,IAAI,CAACnE,iBAAiB,IAAI,CAAC,IAAI,CAACA,iBAAiB,CAAC,CAAC,EAAE;MACvD;IACF;IAEA,MAAMsE,OAAO,GAAGA,CAAA,KAAM;MACpB,IAAIL,gBAAgB,IAAI,OAAOA,gBAAgB,KAAK,UAAU,EAAE;QAC9D,OAAOZ,OAAO,CAACkB,OAAO,CAACN,gBAAgB,CAAC,CAAC,CAAC;MAC5C;MACA,OAAO,IAAI,CAACO,WAAW,CAAC,CAAC;IAC3B,CAAC;IAED,IAAIP,gBAAgB,IAAI,OAAOA,gBAAgB,KAAK,UAAU,EAAE;MAC9DG,WAAW,CAAC,MAAMH,gBAAgB,CAAC,CAAC,EAAED,QAAQ,GAAG,IAAI,CAAC;IACxD,CAAC,MAAM;MACLI,WAAW,CAAC,MAAM;QAChBE,OAAO,CAAC,CAAC,CAACG,KAAK,CAACjB,GAAG,IAAI;UACrBb,OAAO,CAACc,KAAK,CAAC,GAAG,IAAI,CAACpD,UAAU,0BAA0B,EAAEmD,GAAG,CAAC;QAClE,CAAC,CAAC;MACJ,CAAC,EAAEQ,QAAQ,GAAG,IAAI,CAAC;IACrB;;IAEA;IACAM,OAAO,CAAC,CAAC,CAACG,KAAK,CAACjB,GAAG,IAAI;MACrBb,OAAO,CAACc,KAAK,CAAC,GAAG,IAAI,CAACpD,UAAU,oCAAoC,EAAEmD,GAAG,CAAC;IAC5E,CAAC,CAAC;IAEF,IAAIkB,UAAU,GAAG,MAAM;IACvB,IAAI;MACF,IAAI,IAAI,CAAClF,cAAc,IAAI,IAAI,CAACA,cAAc,CAACmF,IAAI,CAAC,CAAC,EAAE;QACrDD,UAAU,GAAG,IAAInG,GAAG,CAAC,IAAI,CAACiB,cAAc,CAACmF,IAAI,CAAC,CAAC,CAAC,CAACC,MAAM;MACzD;IACF,CAAC,CAAC,MAAM;MACNF,UAAU,GAAG,aAAa;IAC5B;IACA/B,OAAO,CAACuB,IAAI,CACV,GAAG,IAAI,CAAC7D,UAAU,2CAA2C,IAAI,CAACR,WAAW,YAAY6E,UAAU,GACrG,CAAC;EACH,CAAC;EAEDF,WAAW,GAAG,MAAAA,CAAA,KAAY;IACxB,OAAO,IAAI,CAACvB,YAAY,CAAC,CAAC;EAC5B,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE4B,SAAS,GAAGA,CAACb,QAAQ,EAAEC,gBAAgB,GAAGX,SAAS,KAAK;IACtD,IAAI,CAACS,UAAU,CAACC,QAAQ,EAAEC,gBAAgB,CAAC;EAC7C,CAAC;;EAED;AACF;AACA;AACA;EACEa,OAAO,GAAG,MAAAA,CAAA,KAAY;IACpB,IAAI,IAAI,CAAC1F,OAAO,EAAE;MAChB,MAAM,IAAI,CAAC2F,aAAa,CAAC,CAAC;IAC5B;IACAnG,OAAO,CAACoG,IAAI,CAAC,CAAC,CAAC;EACjB,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE5D,gBAAgB,GAAG,MAAMjB,gBAAgB,IAAI;IAC3C;EAAA,CACD;;EAED;AACF;AACA;AACA;EACE4E,aAAa,GAAG,MAAAA,CAAA,KAAY;IAC1B,IACE,IAAI,CAAC5E,gBAAgB,IACrB,IAAI,CAACX,cAAc,IACnB,IAAI,CAACA,cAAc,CAACmF,IAAI,CAAC,CAAC,EAC1B;MACA,MAAM,IAAI,CAACM,qBAAqB,CAAC,CAAC,CAACR,KAAK,CAACjB,GAAG,IAAI;QAC9Cb,OAAO,CAACuB,IAAI,CACV,GAAG,IAAI,CAAC7D,UAAU,uCAAuC,EACzDmD,GAAG,CAAC0B,OACN,CAAC;MACH,CAAC,CAAC;IACJ;EACF,CAAC;;EAED;AACF;AACA;AACA;EACED,qBAAqB,GAAGA,CAAA,KAAM;IAC5B,MAAME,GAAG,GAAGC,CAAC,IAAIC,MAAM,CAACD,CAAC,CAAC,CAACE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAACA,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;IACtE,MAAMC,QAAQ,GAAG,SAASJ,GAAG,CAAC,IAAI,CAACxG,OAAO,CAAC,cAAcwG,GAAG,CAC1D,IAAI,CAACpG,MACP,CAAC,mBAAmBoG,GAAG,CAAC,IAAI,CAAClG,WAAW,CAAC,IAAI;IAC7C,IAAI2F,MAAM;IACV,IAAI;MACF,MAAMY,CAAC,GAAG,IAAIjH,GAAG,CAAC,CAAC,IAAI,CAACiB,cAAc,IAAI,EAAE,EAAEmF,IAAI,CAAC,CAAC,CAAC;MACrDC,MAAM,GAAGY,CAAC,CAACZ,MAAM;IACnB,CAAC,CAAC,MAAM;MACN,OAAOvB,OAAO,CAACoC,MAAM,CAAC,IAAIC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtD;IACA,MAAMC,IAAI,GAAG,4CAA4CC,kBAAkB,CACzEL,QACF,CAAC,EAAE;IACH,OAAO,IAAIlC,OAAO,CAAC,CAACkB,OAAO,EAAEkB,MAAM,KAAK;MACtC,MAAMD,CAAC,GAAG,IAAIjH,GAAG,CAACqG,MAAM,CAAC;MACzB,MAAMiB,GAAG,GAAG,CAACL,CAAC,CAACM,QAAQ,KAAK,QAAQ,GAAGzH,KAAK,GAAGC,IAAI,EAAEyH,OAAO,CAC1D;QACEC,QAAQ,EAAER,CAAC,CAACQ,QAAQ;QACpBC,IAAI,EAAET,CAAC,CAACS,IAAI,KAAKT,CAAC,CAACM,QAAQ,KAAK,QAAQ,GAAG,GAAG,GAAG,EAAE,CAAC;QACpDH,IAAI;QACJO,MAAM,EAAE,MAAM;QACdC,OAAO,EAAE;UACP,gBAAgB,EAAE,GAAG;UACrBC,aAAa,EAAE,IAAI,CAAC1G,SAAS,GACzB,SAAS,IAAI,CAACA,SAAS,EAAE,GACzB4D;QACN,CAAC;QACD+C,KAAK,EACHb,CAAC,CAACM,QAAQ,KAAK,QAAQ,GACnB,IAAIzH,KAAK,CAACiI,KAAK,CAAC;UAAEC,SAAS,EAAE;QAAM,CAAC,CAAC,GACrCjD;MACR,CAAC,EACDkD,GAAG,IAAI;QACL,IAAIA,GAAG,CAACC,UAAU,IAAI,GAAG,IAAID,GAAG,CAACC,UAAU,GAAG,GAAG,EAAElC,OAAO,CAAC,CAAC,MACvD;UACH,IAAIjC,IAAI,GAAG,EAAE;UACbkE,GAAG,CAACE,EAAE,CAAC,MAAM,EAAEC,KAAK,IAAI;YACtBrE,IAAI,IAAIqE,KAAK;UACf,CAAC,CAAC;UACFH,GAAG,CAACE,EAAE,CAAC,KAAK,EAAE,MACZjB,MAAM,CAAC,IAAIC,KAAK,CAAC,kBAAkBc,GAAG,CAACC,UAAU,IAAInE,IAAI,EAAE,CAAC,CAC9D,CAAC;QACH;MACF,CACF,CAAC;MACDuD,GAAG,CAACa,EAAE,CAAC,OAAO,EAAEjB,MAAM,CAAC;MACvBI,GAAG,CAACe,GAAG,CAAC,CAAC;IACX,CAAC,CAAC;EACJ,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;EACElD,WAAW,GAAG,MAAAA,CAAOmD,MAAM,GAAG,CAAC,CAAC,KAAK;IACnC,IAAI,IAAI,CAAC5G,kBAAkB,EAAE;MAC3B0C,OAAO,CAACuB,IAAI,CACV,GAAG,IAAI,CAAC7D,UAAU,2DACpB,CAAC;MACD,OAAOgD,OAAO,CAACkB,OAAO,CAAC,CAAC;IAC1B;IACA,IAAI,CAAC,IAAI,CAAC/E,cAAc,IAAI,CAAC,IAAI,CAACA,cAAc,CAACmF,IAAI,CAAC,CAAC,EAAE;MACvDhC,OAAO,CAACuB,IAAI,CACV,GAAG,IAAI,CAAC7D,UAAU,2DACpB,CAAC;MACD,OAAOgD,OAAO,CAACkB,OAAO,CAAC,CAAC;IAC1B;IACA,OAAO,IAAI,CAACuC,cAAc,CAAC,CAAC;EAC9B,CAAC;;EAED;AACF;AACA;AACA;EACEA,cAAc,GAAGA,CAAA,KAAM;IACrB,IAAIC,OAAO,GAAG,CAAC,IAAI,CAACvH,cAAc,IAAI,EAAE,EAAEmF,IAAI,CAAC,CAAC;IAChD,IAAI;MACF,MAAMa,CAAC,GAAG,IAAIjH,GAAG,CAACwI,OAAO,CAAC;MAC1B,IAAI,CAACvB,CAAC,CAACwB,QAAQ,IAAIxB,CAAC,CAACwB,QAAQ,KAAK,GAAG,IAAIxB,CAAC,CAACwB,QAAQ,KAAK,UAAU,EAAE;QAClED,OAAO,GAAG,GAAGvB,CAAC,CAACZ,MAAM,4BAA4BY,CAAC,CAACyB,MAAM,EAAE;MAC7D;IACF,CAAC,CAAC,MAAM;MACN;IAAA;IAEF,OAAO,IAAI5D,OAAO,CAAC,CAACkB,OAAO,EAAEkB,MAAM,KAAK;MACtC,MAAMD,CAAC,GAAG,IAAIjH,GAAG,CAACwI,OAAO,CAAC;MAC1B,MAAMlB,GAAG,GAAG,CAACL,CAAC,CAACM,QAAQ,KAAK,QAAQ,GAAGzH,KAAK,GAAGC,IAAI,EAAEyH,OAAO,CAC1D;QACEC,QAAQ,EAAER,CAAC,CAACQ,QAAQ;QACpBC,IAAI,EAAET,CAAC,CAACS,IAAI,KAAKT,CAAC,CAACM,QAAQ,KAAK,QAAQ,GAAG,GAAG,GAAG,EAAE,CAAC;QACpDH,IAAI,EAAEH,CAAC,CAACwB,QAAQ,GAAGxB,CAAC,CAACyB,MAAM;QAC3Bf,MAAM,EAAE,MAAM;QACdC,OAAO,EAAE;UACP,cAAc,EAAEhI,MAAM,CAACsC,QAAQ,CAACyG,WAAW;UAC3Cd,aAAa,EAAE,IAAI,CAAC1G,SAAS,GACzB,SAAS,IAAI,CAACA,SAAS,EAAE,GACzB4D;QACN,CAAC;QACD+C,KAAK,EACHb,CAAC,CAACM,QAAQ,KAAK,QAAQ,GACnB,IAAIzH,KAAK,CAACiI,KAAK,CAAC;UAAEC,SAAS,EAAE;QAAK,CAAC,CAAC,GACpCjD;MACR,CAAC,EACDkD,GAAG,IAAI;QACL,IAAIA,GAAG,CAACC,UAAU,IAAI,GAAG,IAAID,GAAG,CAACC,UAAU,GAAG,GAAG,EAAE;UACjDlC,OAAO,CAAC,CAAC;QACX,CAAC,MAAM;UACL,IAAIjC,IAAI,GAAG,EAAE;UACbkE,GAAG,CAACE,EAAE,CAAC,MAAM,EAAEC,KAAK,IAAI;YACtBrE,IAAI,IAAIqE,KAAK;UACf,CAAC,CAAC;UACFH,GAAG,CAACE,EAAE,CAAC,KAAK,EAAE,MACZjB,MAAM,CAAC,IAAIC,KAAK,CAAC,gBAAgBc,GAAG,CAACC,UAAU,IAAInE,IAAI,EAAE,CAAC,CAC5D,CAAC;QACH;MACF,CACF,CAAC;MACDuD,GAAG,CAACa,EAAE,CAAC,OAAO,EAAEjB,MAAM,CAAC;MACvB,IAAI,CAACnF,SAAS,CACXqD,OAAO,CAAC,CAAC,CACTwD,IAAI,CAACxD,OAAO,IAAI;QACfkC,GAAG,CAACuB,SAAS,CAAC,gBAAgB,EAAEC,MAAM,CAACC,UAAU,CAAC3D,OAAO,EAAE,MAAM,CAAC,CAAC;QACnEkC,GAAG,CAACe,GAAG,CAACjD,OAAO,EAAE,MAAM,CAAC;MAC1B,CAAC,CAAC,CACDc,KAAK,CAACgB,MAAM,CAAC;IAClB,CAAC,CAAC;EACJ,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;EACE8B,iBAAiB,GAAGA,CAACC,MAAM,GAAG,EAAE,KAAK;IACnC,OAAO,CAAC,GAAG5F,MAAM,CAACC,IAAI,CAAC,IAAI,CAACnB,aAAa,CAAC,EAAE,GAAG8G,MAAM,CAAC;EACxD,CAAC;;EAED;AACF;AACA;AACA;AACA;AACA;AACA;EACEC,8BAA8B,GAAGA,CAACD,MAAM,GAAG,EAAE,KAAK;IAChD,OAAO,CAAC,GAAG5F,MAAM,CAACC,IAAI,CAAC,IAAI,CAACf,0BAA0B,CAAC,EAAE,GAAG0G,MAAM,CAAC;EACrE,CAAC;EAEDE,gBAAgB,GAAGA,CAACF,MAAM,GAAG,EAAE,KAAK;IAClC,OAAO,IAAI,CAAC9G,aAAa;EAC3B,CAAC;EAEDW,mBAAmB,GAAGA,CAAA,KAAM;IAC1BzC,OAAO,CAAC8H,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC5B,OAAO,CAAC;IAClClG,OAAO,CAAC8H,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC5B,OAAO,CAAC;EACrC,CAAC;;EAED;;EAEA,IAAI6C,cAAcA,CAAA,EAAG;IACnB,OAAO,IAAI,CAACvI,OAAO;EACrB;EAEA,IAAIsD,gBAAgBA,CAAA,EAAG;IACrB,OAAO,IAAI,CAACpD,SAAS;EACvB;EAEA,IAAIsI,QAAQA,CAAA,EAAG;IACb,OAAO,IAAI,CAACtH,SAAS;EACvB;EAEA,MAAMuH,kBAAkBA,CAAA,EAAG;IACzB,OAAO,IAAI,CAACvH,SAAS,CAACqD,OAAO,CAAC,CAAC;EACjC;EAEAmE,iBAAiBA,CAAA,EAAG;IAClB,OAAO,OAAOjC,GAAG,EAAEW,GAAG,KAAK;MACzB,IAAI;QACF,MAAM7C,OAAO,GAAG,MAAM,IAAI,CAACkE,kBAAkB,CAAC,CAAC;QAC/CrB,GAAG,CAACjD,GAAG,CAAC,cAAc,EAAEpF,MAAM,CAACsC,QAAQ,CAACyG,WAAW,CAAC;QACpDV,GAAG,CAACI,GAAG,CAACjD,OAAO,CAAC;MAClB,CAAC,CAAC,OAAOH,GAAG,EAAE;QACZb,OAAO,CAACc,KAAK,CAAC,GAAG,IAAI,CAACpD,UAAU,yBAAyB,EAAEmD,GAAG,CAAC;QAC/DgD,GAAG,CAACuB,MAAM,CAAC,GAAG,CAAC,CAACnB,GAAG,CAAC,2BAA2B,CAAC;MAClD;IACF,CAAC;EACH;AACF;AAEAoB,MAAM,CAACC,OAAO,GAAG;EAAEzJ;AAAkB,CAAC","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"baseMetricsClient.js","names":["client","require","https","http","URL","BaseMetricsClient","constructor","config","appName","process","env","BUILD_APP_NAME","dynoId","HOSTNAME","processType","BUILD_DYNO_PROCESS_TYPE","includeNodeDefaultMetrics","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","removeOldMetrics","METRICS_REMOVE_OLD_METRICS","prefixLogs","_registry","Registry","collectDefaultMetrics","register","defaultLabels","app","dyno_id","process_type","defaultLabelsWithoutDynoId","gateway","gauges","counters","countersFunctions","gaugeUpdaters","_clearOldWorkers","_setCleanupHandlers","keepProcessAliveWhenDisabled","createGauge","name","help","updateFn","labelNames","Object","keys","g","Gauge","registers","createCounter","useLabelsWithoutDynoId","defaultSet","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","_idleInterval","setInterval","clearInterval","runPush","resolve","pushMetrics","catch","pushOrigin","trim","origin","startPush","cleanup","gatewayDelete","exit","_deleteFromVMByLabels","message","esc","s","String","replace","selector","u","reject","Error","path","encodeURIComponent","req","protocol","request","hostname","port","method","headers","Authorization","agent","Agent","keepAlive","res","statusCode","on","chunk","end","params","_pushToVMAgent","pushUrl","pathname","search","contentType","then","setHeader","Buffer","byteLength","withDefaultLabels","labels","withDefaultLabelsWithoutDynoId","getDefaultLabels","metricsEnabled","registry","getMetricsAsString","metricsMiddleware","status","module","exports"],"sources":["../../src/metrics/baseMetricsClient.js"],"sourcesContent":["const client = require('prom-client')\nconst https = require('https')\nconst http = require('http')\nconst { URL } = require('url')\n\n/**\n * BaseMetricsClient provides common functionality for all metrics clients.\n * Handles registry setup, push to remote (VM-agent), default labels, and common operations.\n * Always pushes registry to the configured URL (POST Prometheus text format + Basic auth). No Pushgateway.\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] Push URL (VM-agent import endpoint, e.g. .../api/v1/import/prometheus). /metrics is for GET (scrape), not POST (push).\n * @param {string} [config.pushgatewaySecret] Basic auth secret (Base64 of user:password)\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 * @param {boolean} [config.includeNodeDefaultMetrics] Register prom-client default process metrics (heap, etc.); defaults true unless MetricsClient forces false for web+Redis HTTP recording dynos.\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.includeNodeDefaultMetrics =\n config.includeNodeDefaultMetrics !== false\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 this.removeOldMetrics =\n config.removeOldMetrics ??\n process.env.METRICS_REMOVE_OLD_METRICS === 'true'\n\n this.prefixLogs = `[${this.processType}] [${this.appName}] [${this.dynoId}] [Monitoring]`\n\n this._registry = new client.Registry()\n if (this.includeNodeDefaultMetrics) {\n client.collectDefaultMetrics({ register: this._registry })\n }\n\n this.defaultLabels = {\n app: this.appName,\n dyno_id: this.dynoId,\n process_type: this.processType,\n }\n\n /** Default labels without dyno_id (for HTTP metrics so dyno_id is not included). */\n this.defaultLabelsWithoutDynoId = {\n app: this.appName,\n process_type: this.processType,\n }\n\n // Always push to configured URL (VM-agent). No Pushgateway.\n this.gateway = null\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 this.keepProcessAliveWhenDisabled = true\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 * @param {boolean} [params.useLabelsWithoutDynoId=false] - If true, counter uses app/process_type only (no dyno_id). Use for HTTP metrics.\n *\n * @returns {(labels?: Object, incrementValue?: number) => void}\n * A function to increment the counter.\n * Usage: (labels?, incrementValue?)\n */\n createCounter({\n name,\n help,\n labelNames = Object.keys(this.defaultLabels),\n useLabelsWithoutDynoId = false,\n }) {\n if (this.counters[name]) return this.countersFunctions[name]\n\n const defaultSet = useLabelsWithoutDynoId\n ? this.defaultLabelsWithoutDynoId\n : this.defaultLabels\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({ ...defaultSet, ...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 if (this.keepProcessAliveWhenDisabled && !this._idleInterval) {\n this._idleInterval = setInterval(() => {}, 60 * 60 * 1000)\n }\n return\n }\n\n if (this._idleInterval) {\n clearInterval(this._idleInterval)\n this._idleInterval = null\n }\n\n if (this.startupValidation && !this.startupValidation()) {\n return\n }\n\n const runPush = () => {\n if (customPushMetics && typeof customPushMetics === 'function') {\n return Promise.resolve(customPushMetics())\n }\n return this.pushMetrics()\n }\n\n if (customPushMetics && typeof customPushMetics === 'function') {\n setInterval(() => customPushMetics(), interval * 1000)\n } else {\n setInterval(() => {\n runPush().catch(err => {\n console.error(`${this.prefixLogs} Failed to push metrics:`, err)\n })\n }, interval * 1000)\n }\n\n // First push immediately so metrics appear without waiting for the first interval\n runPush().catch(err => {\n console.error(`${this.prefixLogs} Failed to push metrics (initial):`, err)\n })\n\n let pushOrigin = 'none'\n try {\n if (this.pushgatewayUrl && this.pushgatewayUrl.trim()) {\n pushOrigin = new URL(this.pushgatewayUrl.trim()).origin\n }\n } catch {\n pushOrigin = 'invalid URL'\n }\n console.warn(\n `${this.prefixLogs} Metrics collection started. (interval: ${this.intervalSec}s, push: ${pushOrigin})`\n )\n }\n\n /** Must be a prototype method (not a class field) so subclasses can `super.pushMetrics()`. */\n async pushMetrics() {\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 // No Pushgateway; VM-agent does not support per-instance delete. Skip.\n }\n\n /**\n * On shutdown: optionally delete this instance's metrics from VictoriaMetrics (by app, dyno_id, process_type).\n * @returns {Promise<void>}\n */\n gatewayDelete = async () => {\n if (\n this.removeOldMetrics &&\n this.pushgatewayUrl &&\n this.pushgatewayUrl.trim()\n ) {\n await this._deleteFromVMByLabels().catch(err => {\n console.warn(\n `${this.prefixLogs} Deletion from VM on shutdown failed:`,\n err.message\n )\n })\n }\n }\n\n /**\n * Call VictoriaMetrics delete_series API to remove all series matching this instance's labels (app, dyno_id, process_type).\n * @private\n */\n _deleteFromVMByLabels = () => {\n const esc = s => String(s).replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n const selector = `{app=\"${esc(this.appName)}\",dyno_id=\"${esc(\n this.dynoId\n )}\",process_type=\"${esc(this.processType)}\"}`\n let origin\n try {\n const u = new URL((this.pushgatewayUrl || '').trim())\n origin = u.origin\n } catch {\n return Promise.reject(new Error('Invalid push URL'))\n }\n const path = `/api/v1/admin/tsdb/delete_series?match[]=${encodeURIComponent(\n selector\n )}`\n return new Promise((resolve, reject) => {\n const u = new URL(origin)\n const req = (u.protocol === 'https:' ? https : http).request(\n {\n hostname: u.hostname,\n port: u.port || (u.protocol === 'https:' ? 443 : 80),\n path,\n method: 'POST',\n headers: {\n 'Content-Length': '0',\n Authorization: this.authToken\n ? `Basic ${this.authToken}`\n : undefined,\n },\n agent:\n u.protocol === 'https:'\n ? new https.Agent({ keepAlive: false })\n : undefined,\n },\n res => {\n if (res.statusCode >= 200 && res.statusCode < 300) resolve()\n else {\n let data = ''\n res.on('data', chunk => {\n data += chunk\n })\n res.on('end', () =>\n reject(new Error(`Delete failed: ${res.statusCode} ${data}`))\n )\n }\n }\n )\n req.on('error', reject)\n req.end()\n })\n }\n\n /**\n * Push registry to configured URL (VM-agent). POST Prometheus text format + Basic auth.\n *\n * @param {object} [params] Unused; kept for API compatibility.\n * @returns {Promise<void>}\n */\n gatewayPush = async (params = {}) => {\n if (this.disablePushgateway) {\n console.warn(\n `${this.prefixLogs} Metrics push skipped: METRICS_DISABLE_PUSHGATEWAY is set`\n )\n return Promise.resolve()\n }\n if (!this.pushgatewayUrl || !this.pushgatewayUrl.trim()) {\n console.warn(\n `${this.prefixLogs} Metrics push skipped: METRICS_PUSHGATEWAY_URL is not set`\n )\n return Promise.resolve()\n }\n return this._pushToVMAgent()\n }\n\n /**\n * POST registry (Prometheus text format) to VM-agent. VM-agent accepts push at /api/v1/import/prometheus; /metrics is GET (scrape) only.\n * @private\n */\n _pushToVMAgent = () => {\n let pushUrl = (this.pushgatewayUrl || '').trim()\n try {\n const u = new URL(pushUrl)\n if (!u.pathname || u.pathname === '/' || u.pathname === '/metrics') {\n pushUrl = `${u.origin}/api/v1/import/prometheus${u.search}`\n }\n } catch {\n // leave pushUrl as-is\n }\n return new Promise((resolve, reject) => {\n const u = new URL(pushUrl)\n const req = (u.protocol === 'https:' ? https : http).request(\n {\n hostname: u.hostname,\n port: u.port || (u.protocol === 'https:' ? 443 : 80),\n path: u.pathname + u.search,\n method: 'POST',\n headers: {\n 'Content-Type': client.register.contentType,\n Authorization: this.authToken\n ? `Basic ${this.authToken}`\n : undefined,\n },\n agent:\n u.protocol === 'https:'\n ? new https.Agent({ keepAlive: true })\n : undefined,\n },\n res => {\n if (res.statusCode >= 200 && res.statusCode < 300) {\n resolve()\n } else {\n let data = ''\n res.on('data', chunk => {\n data += chunk\n })\n res.on('end', () =>\n reject(new Error(`Push failed: ${res.statusCode} ${data}`))\n )\n }\n }\n )\n req.on('error', reject)\n this._registry\n .metrics()\n .then(metrics => {\n req.setHeader('Content-Length', Buffer.byteLength(metrics, 'utf8'))\n req.end(metrics, 'utf8')\n })\n .catch(reject)\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 /**\n * Merge default labels without dyno_id (`app`, `process_type`) with custom label names.\n * Use for HTTP metrics so dyno_id is not included.\n *\n * @param {string[]} labels Additional label names\n * @returns {string[]} Combined label names\n */\n withDefaultLabelsWithoutDynoId = (labels = []) => {\n return [...Object.keys(this.defaultLabelsWithoutDynoId), ...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":"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","ignoreList":[]}
|
|
@@ -8,12 +8,40 @@
|
|
|
8
8
|
export class MetricsClient extends BaseMetricsClient {
|
|
9
9
|
/**
|
|
10
10
|
* @param {Object} [config]
|
|
11
|
-
* @param {
|
|
11
|
+
* @param {string} [config.appName] Name of the application
|
|
12
|
+
* @param {string} [config.dynoId] Dyno/instance ID
|
|
13
|
+
* @param {string} [config.processType] Process type (web, worker, metrics, etc.)
|
|
14
|
+
* @param {boolean} [config.enabled] Enable metrics collection
|
|
15
|
+
* @param {boolean} [config.httpMetricsEnabled] Enable HTTP request metrics (app_requests_total, app_requests_total_duration); defaults from METRICS_HTTP_ENABLED
|
|
16
|
+
* @param {boolean} [config.logValues] Log metrics values to console
|
|
17
|
+
* @param {string} [config.pushgatewayUrl] Push URL (VM-agent import endpoint)
|
|
18
|
+
* @param {string} [config.pushgatewaySecret] Basic auth secret (Base64 user:password)
|
|
19
|
+
* @param {number} [config.intervalSec] Interval in seconds for pushing metrics
|
|
20
|
+
* @param {boolean} [config.removeOldMetrics] Enable to clear metrics by service name
|
|
21
|
+
* @param {function} [config.startupValidation] Add to validate on start push
|
|
22
|
+
* @param {boolean} [config.disablePushgateway] Disable pushing to VM-agent (use HTTP scraping instead)
|
|
23
|
+
* @param {boolean} [config.includeNodeDefaultMetrics] Register prom-client default process metrics
|
|
24
|
+
* @param {string} [config.httpMetricsRedisUrl] Overrides METRICS_HTTP_REDIS_URL / REDIS_URL for the HTTP Redis store
|
|
25
|
+
* @param {boolean} [config.httpMetricsRedisAggregation] When unset, on if Redis + HTTP metrics; set false to force in-process HTTP counters only
|
|
12
26
|
*/
|
|
13
27
|
constructor(config?: {
|
|
28
|
+
appName?: string | undefined;
|
|
29
|
+
dynoId?: string | undefined;
|
|
30
|
+
processType?: string | undefined;
|
|
31
|
+
enabled?: boolean | undefined;
|
|
32
|
+
httpMetricsEnabled?: boolean | undefined;
|
|
33
|
+
logValues?: boolean | undefined;
|
|
34
|
+
pushgatewayUrl?: string | undefined;
|
|
35
|
+
pushgatewaySecret?: string | undefined;
|
|
36
|
+
intervalSec?: number | undefined;
|
|
37
|
+
removeOldMetrics?: boolean | undefined;
|
|
38
|
+
startupValidation?: Function | undefined;
|
|
39
|
+
disablePushgateway?: boolean | undefined;
|
|
40
|
+
includeNodeDefaultMetrics?: boolean | undefined;
|
|
41
|
+
httpMetricsRedisUrl?: string | undefined;
|
|
14
42
|
httpMetricsRedisAggregation?: boolean | undefined;
|
|
15
43
|
} | undefined);
|
|
16
|
-
httpMetricsEnabled:
|
|
44
|
+
httpMetricsEnabled: boolean;
|
|
17
45
|
httpMetricsRedisAggregation: boolean;
|
|
18
46
|
_httpRedisStore: HttpMetricsRedisStore | null;
|
|
19
47
|
_webRedisHttpRecordingOnly: boolean;
|
|
@@ -39,7 +67,13 @@ export class MetricsClient extends BaseMetricsClient {
|
|
|
39
67
|
databaseId?: string | undefined;
|
|
40
68
|
duration: any;
|
|
41
69
|
}): void;
|
|
42
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Start periodic push to VM-agent (`METRICS_PUSHGATEWAY_URL`). Interval defaults to `intervalSec` from config/env.
|
|
72
|
+
* @param {number} [interval] Seconds between pushes; defaults to `this.intervalSec`
|
|
73
|
+
* @param {() => void | Promise<void>} [customPushMetrics] Optional; replaces default push when provided
|
|
74
|
+
* @returns {void}
|
|
75
|
+
*/
|
|
76
|
+
startPush: (interval?: number | undefined, customPushMetrics?: (() => void | Promise<void>) | undefined) => void;
|
|
43
77
|
trackHttpRequestMiddleware: (req: any, res: any, next: any) => void;
|
|
44
78
|
}
|
|
45
79
|
import { BaseMetricsClient } from "./baseMetricsClient";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metricsClient.d.ts","sourceRoot":"","sources":["../../src/metrics/metricsClient.js"],"names":[],"mappings":"AA6BA;;;;;;GAMG;AACH;IACE
|
|
1
|
+
{"version":3,"file":"metricsClient.d.ts","sourceRoot":"","sources":["../../src/metrics/metricsClient.js"],"names":[],"mappings":"AA6BA;;;;;;GAMG;AACH;IACE;;;;;;;;;;;;;;;;;OAiBG;IACH;;;;;;;;;;;;;;;;mBAqFC;IA/CC,4BAA4C;IAC5C,qCAA8D;IAM9D,8CAOU;IAEV,oCAEC;IAED,6BAA2D;IAG3D,iCAAwE;IACxE,+BAA8C;IAgB9C,kCAAqC;IAErC,yBAAyB;IACzB,uBAAgC;IAMlC,iCAQC;IAED,2CAEC;IAED,gCAiFC;IAED,iCAyBC;IAED,2BAeC;IAED,kCASC;IAED,kCAcC;IAED,2BAKC;IAED;;;;;;;aAuCC;IAED;;;;;OAKG;IACH,sEAHiB,IAAI,GAAG,QAAQ,IAAI,CAAC,kBACxB,IAAI,CAoBhB;IAuBD,oEA+BC;CACF"}
|
|
@@ -42,7 +42,21 @@ function isMetricsExporterProcessType(processType) {
|
|
|
42
42
|
class MetricsClient extends BaseMetricsClient {
|
|
43
43
|
/**
|
|
44
44
|
* @param {Object} [config]
|
|
45
|
-
* @param {
|
|
45
|
+
* @param {string} [config.appName] Name of the application
|
|
46
|
+
* @param {string} [config.dynoId] Dyno/instance ID
|
|
47
|
+
* @param {string} [config.processType] Process type (web, worker, metrics, etc.)
|
|
48
|
+
* @param {boolean} [config.enabled] Enable metrics collection
|
|
49
|
+
* @param {boolean} [config.httpMetricsEnabled] Enable HTTP request metrics (app_requests_total, app_requests_total_duration); defaults from METRICS_HTTP_ENABLED
|
|
50
|
+
* @param {boolean} [config.logValues] Log metrics values to console
|
|
51
|
+
* @param {string} [config.pushgatewayUrl] Push URL (VM-agent import endpoint)
|
|
52
|
+
* @param {string} [config.pushgatewaySecret] Basic auth secret (Base64 user:password)
|
|
53
|
+
* @param {number} [config.intervalSec] Interval in seconds for pushing metrics
|
|
54
|
+
* @param {boolean} [config.removeOldMetrics] Enable to clear metrics by service name
|
|
55
|
+
* @param {function} [config.startupValidation] Add to validate on start push
|
|
56
|
+
* @param {boolean} [config.disablePushgateway] Disable pushing to VM-agent (use HTTP scraping instead)
|
|
57
|
+
* @param {boolean} [config.includeNodeDefaultMetrics] Register prom-client default process metrics
|
|
58
|
+
* @param {string} [config.httpMetricsRedisUrl] Overrides METRICS_HTTP_REDIS_URL / REDIS_URL for the HTTP Redis store
|
|
59
|
+
* @param {boolean} [config.httpMetricsRedisAggregation] When unset, on if Redis + HTTP metrics; set false to force in-process HTTP counters only
|
|
46
60
|
*/
|
|
47
61
|
constructor(config = {}) {
|
|
48
62
|
const processTypeBeforeSuper = config.processType || process.env.BUILD_DYNO_PROCESS_TYPE || 'undefined_build_dyno_type';
|
|
@@ -252,6 +266,13 @@ class MetricsClient extends BaseMetricsClient {
|
|
|
252
266
|
databaseId
|
|
253
267
|
}, duration);
|
|
254
268
|
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Start periodic push to VM-agent (`METRICS_PUSHGATEWAY_URL`). Interval defaults to `intervalSec` from config/env.
|
|
272
|
+
* @param {number} [interval] Seconds between pushes; defaults to `this.intervalSec`
|
|
273
|
+
* @param {() => void | Promise<void>} [customPushMetrics] Optional; replaces default push when provided
|
|
274
|
+
* @returns {void}
|
|
275
|
+
*/
|
|
255
276
|
startPush = (interval, customPushMetrics) => {
|
|
256
277
|
if (this._webRedisHttpRecordingOnly) {
|
|
257
278
|
return;
|
|
@@ -265,15 +286,16 @@ class MetricsClient extends BaseMetricsClient {
|
|
|
265
286
|
}
|
|
266
287
|
this._startPush(interval, customPushMetrics);
|
|
267
288
|
};
|
|
268
|
-
|
|
289
|
+
async pushMetrics() {
|
|
269
290
|
if (this._webRedisHttpRecordingOnly) {
|
|
270
291
|
return;
|
|
271
292
|
}
|
|
272
293
|
if (this._httpRedisStore && shouldRunMetricsPush(this) && this.countersFunctions?.app_requests_total && this.countersFunctions?.app_requests_total_duration) {
|
|
273
294
|
await this._httpRedisStore.flushToCounters((labels, value) => this.countersFunctions.app_requests_total(labels, value), (labels, value) => this.countersFunctions.app_requests_total_duration(labels, value));
|
|
274
295
|
}
|
|
275
|
-
return
|
|
276
|
-
|
|
296
|
+
// eslint-disable-next-line consistent-return
|
|
297
|
+
return super.pushMetrics();
|
|
298
|
+
}
|
|
277
299
|
trackHttpRequestMiddleware = (req, res, next) => {
|
|
278
300
|
if (!this.enabled || !this.httpMetricsEnabled || req.method === 'OPTIONS') {
|
|
279
301
|
next();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metricsClient.js","names":["fs","require","os","BaseMetricsClient","shouldRunMetricsPush","HttpMetricsRedisStore","isRedisPeerInstalled","isWebServingDynoContext","processType","dyno","process","env","DYNO","test","isMetricsExporterProcessType","MetricsClient","constructor","config","processTypeBeforeSuper","BUILD_DYNO_PROCESS_TYPE","httpMetricsEnabled","METRICS_HTTP_ENABLED","redisUrl","httpMetricsRedisUrl","METRICS_HTTP_REDIS_URL","REDIS_URL","httpMetricsRedisAggregation","Boolean","console","warn","isWebCtx","webRedisRecordingOnly","NODE_ENV","includeNodeDefaultMetrics","redisKeyProcessType","_httpRedisStore","appName","_webRedisHttpRecordingOnly","exportRuntimeGauges","wcParsed","parseInt","WEB_CONCURRENCY","_bootstrapWebConcurrency","Number","isFinite","_bootstrapHostCpuCount","cpus","length","defaultLabelsWithoutDynoId","app","process_type","_skippedPushWorkerLogged","_lastUsageMicros","_lastCheckTime","Date","now","_initDefaultMetrics","_logMetricsBootstrap","enabled","wc","prefixLogs","isWebRedisHttpRecordingOnly","createGauge","name","help","updateFn","getCpuUsagePercent","getAvailableCPUs","getContainerMemoryUsage","measureLag","getContainerMemoryLimit","uptime","registerHttpCounters","createCounter","labelNames","withDefaultLabelsWithoutDynoId","useLabelsWithoutDynoId","stat","readFileSync","match","currentUsage","deltaUsage","deltaTime","cpuMaxPath","existsSync","quotaStr","periodStr","trim","split","memoryUsage","rss","path","val","parsed","totalmem","Promise","resolve","start","setImmediate","trackHttpRequest","method","route","status_code","appId","databaseId","duration","record","countersFunctions","app_requests_total","app_requests_total_duration","startPush","interval","customPushMetrics","METRICS_SUPPRESS_SKIP_PUSH_LOG","_startPush","pushMetrics","flushToCounters","labels","value","prototype","call","trackHttpRequestMiddleware","req","res","next","on","params","body","query","datasourceId","statusCode","module","exports"],"sources":["../../src/metrics/metricsClient.js"],"sourcesContent":["const fs = require('fs')\nconst os = require('os')\nconst { BaseMetricsClient } = require('./baseMetricsClient')\nconst { shouldRunMetricsPush } = require('./shouldRunMetricsPush')\nconst {\n HttpMetricsRedisStore,\n isRedisPeerInstalled,\n} = require('./httpMetricsRedisStore')\n\n/**\n * Heroku-style: DYNO=web.1 → web serving; DYNO=metrics.1 → VM-agent exporter (Procfile `metrics:`).\n * Without DYNO (local Docker), falls back to BUILD_DYNO_PROCESS_TYPE === 'web'.\n */\nfunction isWebServingDynoContext(processType) {\n const dyno = process.env.DYNO || ''\n if (dyno) {\n return /^web\\./.test(dyno)\n }\n return processType === 'web'\n}\n\nfunction isMetricsExporterProcessType(processType) {\n const dyno = process.env.DYNO || ''\n if (dyno) {\n return /^metrics\\./.test(dyno)\n }\n return processType === 'metrics'\n}\n\n/**\n * MetricsClient handles Prometheus metrics collection and push.\n *\n * **Redis HTTP:** When `METRICS_HTTP_ENABLED` and a Redis URL exist, HTTP counts use Redis\n * (key segment from BUILD_APP_NAME + process type). Production **web.*** dynos only write Redis;\n * run Procfile **`metrics`** + **metrics-exporter.js** to drain and POST. Tests: `httpMetricsRedisAggregation: false`.\n */\nclass MetricsClient extends BaseMetricsClient {\n /**\n * @param {Object} [config]\n * @param {boolean} [config.httpMetricsRedisAggregation] auto when Redis+HTTP; `false` to force off\n */\n constructor(config = {}) {\n const processTypeBeforeSuper =\n config.processType || process.env.BUILD_DYNO_PROCESS_TYPE || 'undefined_build_dyno_type'\n\n const httpMetricsEnabled =\n config.httpMetricsEnabled ??\n process.env.METRICS_HTTP_ENABLED === 'true' ??\n false\n\n const redisUrl =\n config.httpMetricsRedisUrl ||\n process.env.METRICS_HTTP_REDIS_URL ||\n process.env.REDIS_URL ||\n ''\n\n let httpMetricsRedisAggregation =\n Boolean(redisUrl) &&\n Boolean(httpMetricsEnabled) &&\n config.httpMetricsRedisAggregation !== false\n\n if (httpMetricsRedisAggregation && !isRedisPeerInstalled()) {\n console.warn(\n '[MetricsClient] METRICS_HTTP_ENABLED with REDIS_URL needs the peer package `redis` in your application (npm install redis@3). Falling back to in-process HTTP counters. @adalo/metrics does not bundle redis.'\n )\n httpMetricsRedisAggregation = false\n }\n\n const isWebCtx = isWebServingDynoContext(processTypeBeforeSuper)\n const webRedisRecordingOnly =\n Boolean(httpMetricsRedisAggregation) &&\n isWebCtx &&\n process.env.NODE_ENV === 'production'\n\n super({\n ...config,\n ...(webRedisRecordingOnly ? { includeNodeDefaultMetrics: false } : {}),\n })\n\n this.httpMetricsEnabled = httpMetricsEnabled\n this.httpMetricsRedisAggregation = httpMetricsRedisAggregation\n\n const redisKeyProcessType = isMetricsExporterProcessType(this.processType)\n ? 'web'\n : this.processType\n\n this._httpRedisStore =\n this.httpMetricsEnabled && this.httpMetricsRedisAggregation\n ? new HttpMetricsRedisStore({\n redisUrl,\n appName: this.appName,\n processType: redisKeyProcessType,\n })\n : null\n\n this._webRedisHttpRecordingOnly = Boolean(\n webRedisRecordingOnly && this._httpRedisStore\n )\n\n this.exportRuntimeGauges = !this._webRedisHttpRecordingOnly\n\n const wcParsed = parseInt(process.env.WEB_CONCURRENCY || '', 10)\n this._bootstrapWebConcurrency = Number.isFinite(wcParsed) ? wcParsed : 0\n this._bootstrapHostCpuCount = os.cpus().length\n\n if (this.httpMetricsRedisAggregation && redisUrl) {\n if (isMetricsExporterProcessType(this.processType)) {\n this.defaultLabelsWithoutDynoId = {\n app: this.appName,\n process_type: 'web',\n }\n } else if (!this._webRedisHttpRecordingOnly) {\n this.defaultLabelsWithoutDynoId = {\n app: this.appName,\n process_type: this.processType,\n }\n }\n }\n\n this._skippedPushWorkerLogged = false\n\n this._lastUsageMicros = 0\n this._lastCheckTime = Date.now()\n\n this._initDefaultMetrics()\n this._logMetricsBootstrap()\n }\n\n _logMetricsBootstrap = () => {\n if (!this.enabled) {\n return\n }\n const wc = process.env.WEB_CONCURRENCY || ''\n console.warn(\n `${this.prefixLogs} metrics bootstrap WEB_CONCURRENCY=${wc || '(unset)'} host_cpus=${this._bootstrapHostCpuCount} dyno=${process.env.DYNO || '(unset)'} redis_http=${this.httpMetricsRedisAggregation} web_redis_only=${this._webRedisHttpRecordingOnly}`\n )\n }\n\n get isWebRedisHttpRecordingOnly() {\n return Boolean(this._webRedisHttpRecordingOnly)\n }\n\n _initDefaultMetrics = () => {\n if (this.exportRuntimeGauges) {\n this.createGauge({\n name: 'app_process_cpu_usage_percent',\n help: 'Current CPU usage of the Node.js process in percent',\n updateFn: this.getCpuUsagePercent,\n })\n\n this.createGauge({\n name: 'app_available_cpu_count',\n help: 'How many CPU cores are available to this process',\n updateFn: this.getAvailableCPUs,\n })\n\n this.createGauge({\n name: 'app_container_memory_usage_bytes',\n help: 'Current container RAM usage from cgroup',\n updateFn: this.getContainerMemoryUsage,\n })\n\n this.createGauge({\n name: 'app_event_loop_lag_ms',\n help: 'Estimated event loop lag in milliseconds',\n updateFn: this.measureLag,\n })\n\n this.createGauge({\n name: 'app_container_memory_limit_bytes',\n help: 'Max RAM available to container from cgroup (memory.max)',\n updateFn: this.getContainerMemoryLimit,\n })\n\n this.createGauge({\n name: 'app_uptime_seconds',\n help: 'How long the process has been running',\n updateFn: process.uptime,\n })\n\n this.createGauge({\n name: 'app_bootstrap_web_concurrency',\n help: 'WEB_CONCURRENCY at process start (diagnostic; 0 if unset/invalid)',\n updateFn: () => this._bootstrapWebConcurrency,\n })\n\n this.createGauge({\n name: 'app_bootstrap_host_cpu_count',\n help: 'os.cpus().length at process start (diagnostic)',\n updateFn: () => this._bootstrapHostCpuCount,\n })\n }\n\n const registerHttpCounters =\n this.httpMetricsEnabled && !this._webRedisHttpRecordingOnly\n\n if (registerHttpCounters) {\n this.createCounter({\n name: 'app_requests_total',\n help: 'Total number of HTTP requests',\n labelNames: this.withDefaultLabelsWithoutDynoId([\n 'method',\n 'route',\n 'appId',\n 'databaseId',\n 'status_code',\n ]),\n useLabelsWithoutDynoId: true,\n })\n\n this.createCounter({\n name: 'app_requests_total_duration',\n help: 'Total duration of HTTP requests in milliseconds',\n labelNames: this.withDefaultLabelsWithoutDynoId([\n 'method',\n 'route',\n 'appId',\n 'databaseId',\n 'status_code',\n ]),\n useLabelsWithoutDynoId: true,\n })\n }\n }\n\n getCpuUsagePercent = () => {\n try {\n const stat = fs.readFileSync('/sys/fs/cgroup/cpu.stat', 'utf-8')\n const match = stat.match(/usage_usec (\\d+)/)\n if (!match) return 0\n\n const now = Date.now()\n const currentUsage = parseInt(match[1], 10)\n\n if (this._lastUsageMicros === 0) {\n this._lastUsageMicros = currentUsage\n this._lastCheckTime = now\n return 0\n }\n\n const deltaUsage = currentUsage - this._lastUsageMicros\n const deltaTime = now - this._lastCheckTime\n\n this._lastUsageMicros = currentUsage\n this._lastCheckTime = now\n\n return (deltaUsage / (deltaTime * 1000)) * 100\n } catch {\n return 0\n }\n }\n\n getAvailableCPUs() {\n try {\n const cpuMaxPath = '/sys/fs/cgroup/cpu.max'\n if (fs.existsSync(cpuMaxPath)) {\n const [quotaStr, periodStr] = fs\n .readFileSync(cpuMaxPath, 'utf8')\n .trim()\n .split(' ')\n if (quotaStr === 'max') return os.cpus().length\n return parseInt(quotaStr, 10) / parseInt(periodStr, 10)\n }\n return os.cpus().length\n } catch {\n return 1\n }\n }\n\n getContainerMemoryUsage() {\n try {\n return parseInt(\n fs.readFileSync('/sys/fs/cgroup/memory.current', 'utf-8').trim(),\n 10\n )\n } catch {\n return process.memoryUsage().rss\n }\n }\n\n getContainerMemoryLimit() {\n try {\n const path = '/sys/fs/cgroup/memory.max'\n if (fs.existsSync(path)) {\n const val = fs.readFileSync(path, 'utf-8').trim()\n if (val !== 'max') {\n const parsed = parseInt(val, 10)\n if (parsed && parsed < os.totalmem()) return parsed\n }\n }\n return os.totalmem()\n } catch {\n return os.totalmem()\n }\n }\n\n measureLag() {\n return new Promise(resolve => {\n const start = Date.now()\n setImmediate(() => resolve(Date.now() - start))\n })\n }\n\n trackHttpRequest({\n method,\n route,\n status_code,\n appId = '',\n databaseId = '',\n duration,\n }) {\n if (!this.httpMetricsEnabled) return\n\n if (this._httpRedisStore) {\n this._httpRedisStore.record(\n method,\n route,\n status_code,\n appId,\n databaseId,\n duration\n )\n return\n }\n\n this.countersFunctions?.app_requests_total({\n method,\n route,\n status_code,\n appId,\n databaseId,\n })\n this.countersFunctions?.app_requests_total_duration(\n {\n method,\n route,\n status_code,\n appId,\n databaseId,\n },\n duration\n )\n }\n\n startPush = (interval, customPushMetrics) => {\n if (this._webRedisHttpRecordingOnly) {\n return\n }\n if (!shouldRunMetricsPush(this)) {\n if (\n this.enabled &&\n !this._skippedPushWorkerLogged &&\n process.env.METRICS_SUPPRESS_SKIP_PUSH_LOG !== 'true'\n ) {\n console.warn(\n `${this.prefixLogs} Skipping VM-agent push on this worker. METRICS_PUSH_ALL_WORKERS=true restores per-worker push.`\n )\n this._skippedPushWorkerLogged = true\n }\n return\n }\n this._startPush(interval, customPushMetrics)\n }\n\n pushMetrics = async () => {\n if (this._webRedisHttpRecordingOnly) {\n return\n }\n if (\n this._httpRedisStore &&\n shouldRunMetricsPush(this) &&\n this.countersFunctions?.app_requests_total &&\n this.countersFunctions?.app_requests_total_duration\n ) {\n await this._httpRedisStore.flushToCounters(\n (labels, value) =>\n this.countersFunctions.app_requests_total(labels, value),\n (labels, value) =>\n this.countersFunctions.app_requests_total_duration(labels, value)\n )\n }\n return BaseMetricsClient.prototype.pushMetrics.call(this)\n }\n\n trackHttpRequestMiddleware = (req, res, next) => {\n if (!this.enabled || !this.httpMetricsEnabled || req.method === 'OPTIONS') {\n next()\n return\n }\n\n const start = Date.now()\n res.on('finish', () => {\n const route = req.route?.path || req.path || 'unknown'\n const appId =\n req.params?.appId || req.body?.appId || req.query?.appId || ''\n const databaseId =\n req.params?.databaseId ||\n req.body?.databaseId ||\n req.query?.databaseId ||\n req.params?.datasourceId ||\n req.body?.datasourceId ||\n req.query?.datasourceId ||\n ''\n\n this.trackHttpRequest({\n method: req.method,\n route,\n status_code: res.statusCode,\n appId,\n databaseId,\n duration: Date.now() - start,\n })\n })\n\n next()\n }\n}\n\nmodule.exports = { MetricsClient }\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"metricsClient.js","names":["fs","require","os","BaseMetricsClient","shouldRunMetricsPush","HttpMetricsRedisStore","isRedisPeerInstalled","isWebServingDynoContext","processType","dyno","process","env","DYNO","test","isMetricsExporterProcessType","MetricsClient","constructor","config","processTypeBeforeSuper","BUILD_DYNO_PROCESS_TYPE","httpMetricsEnabled","METRICS_HTTP_ENABLED","redisUrl","httpMetricsRedisUrl","METRICS_HTTP_REDIS_URL","REDIS_URL","httpMetricsRedisAggregation","Boolean","console","warn","isWebCtx","webRedisRecordingOnly","NODE_ENV","includeNodeDefaultMetrics","redisKeyProcessType","_httpRedisStore","appName","_webRedisHttpRecordingOnly","exportRuntimeGauges","wcParsed","parseInt","WEB_CONCURRENCY","_bootstrapWebConcurrency","Number","isFinite","_bootstrapHostCpuCount","cpus","length","defaultLabelsWithoutDynoId","app","process_type","_skippedPushWorkerLogged","_lastUsageMicros","_lastCheckTime","Date","now","_initDefaultMetrics","_logMetricsBootstrap","enabled","wc","prefixLogs","isWebRedisHttpRecordingOnly","createGauge","name","help","updateFn","getCpuUsagePercent","getAvailableCPUs","getContainerMemoryUsage","measureLag","getContainerMemoryLimit","uptime","registerHttpCounters","createCounter","labelNames","withDefaultLabelsWithoutDynoId","useLabelsWithoutDynoId","stat","readFileSync","match","currentUsage","deltaUsage","deltaTime","cpuMaxPath","existsSync","quotaStr","periodStr","trim","split","memoryUsage","rss","path","val","parsed","totalmem","Promise","resolve","start","setImmediate","trackHttpRequest","method","route","status_code","appId","databaseId","duration","record","countersFunctions","app_requests_total","app_requests_total_duration","startPush","interval","customPushMetrics","METRICS_SUPPRESS_SKIP_PUSH_LOG","_startPush","pushMetrics","flushToCounters","labels","value","trackHttpRequestMiddleware","req","res","next","on","params","body","query","datasourceId","statusCode","module","exports"],"sources":["../../src/metrics/metricsClient.js"],"sourcesContent":["const fs = require('fs')\nconst os = require('os')\nconst { BaseMetricsClient } = require('./baseMetricsClient')\nconst { shouldRunMetricsPush } = require('./shouldRunMetricsPush')\nconst {\n HttpMetricsRedisStore,\n isRedisPeerInstalled,\n} = require('./httpMetricsRedisStore')\n\n/**\n * Heroku-style: DYNO=web.1 → web serving; DYNO=metrics.1 → VM-agent exporter (Procfile `metrics:`).\n * Without DYNO (local Docker), falls back to BUILD_DYNO_PROCESS_TYPE === 'web'.\n */\nfunction isWebServingDynoContext(processType) {\n const dyno = process.env.DYNO || ''\n if (dyno) {\n return /^web\\./.test(dyno)\n }\n return processType === 'web'\n}\n\nfunction isMetricsExporterProcessType(processType) {\n const dyno = process.env.DYNO || ''\n if (dyno) {\n return /^metrics\\./.test(dyno)\n }\n return processType === 'metrics'\n}\n\n/**\n * MetricsClient handles Prometheus metrics collection and push.\n *\n * **Redis HTTP:** When `METRICS_HTTP_ENABLED` and a Redis URL exist, HTTP counts use Redis\n * (key segment from BUILD_APP_NAME + process type). Production **web.*** dynos only write Redis;\n * run Procfile **`metrics`** + **metrics-exporter.js** to drain and POST. Tests: `httpMetricsRedisAggregation: false`.\n */\nclass MetricsClient extends 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, metrics, etc.)\n * @param {boolean} [config.enabled] Enable metrics collection\n * @param {boolean} [config.httpMetricsEnabled] Enable HTTP request metrics (app_requests_total, app_requests_total_duration); defaults from METRICS_HTTP_ENABLED\n * @param {boolean} [config.logValues] Log metrics values to console\n * @param {string} [config.pushgatewayUrl] Push URL (VM-agent import endpoint)\n * @param {string} [config.pushgatewaySecret] Basic auth secret (Base64 user:password)\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 VM-agent (use HTTP scraping instead)\n * @param {boolean} [config.includeNodeDefaultMetrics] Register prom-client default process metrics\n * @param {string} [config.httpMetricsRedisUrl] Overrides METRICS_HTTP_REDIS_URL / REDIS_URL for the HTTP Redis store\n * @param {boolean} [config.httpMetricsRedisAggregation] When unset, on if Redis + HTTP metrics; set false to force in-process HTTP counters only\n */\n constructor(config = {}) {\n const processTypeBeforeSuper =\n config.processType || process.env.BUILD_DYNO_PROCESS_TYPE || 'undefined_build_dyno_type'\n\n const httpMetricsEnabled =\n config.httpMetricsEnabled ??\n process.env.METRICS_HTTP_ENABLED === 'true' ??\n false\n\n const redisUrl =\n config.httpMetricsRedisUrl ||\n process.env.METRICS_HTTP_REDIS_URL ||\n process.env.REDIS_URL ||\n ''\n\n let httpMetricsRedisAggregation =\n Boolean(redisUrl) &&\n Boolean(httpMetricsEnabled) &&\n config.httpMetricsRedisAggregation !== false\n\n if (httpMetricsRedisAggregation && !isRedisPeerInstalled()) {\n console.warn(\n '[MetricsClient] METRICS_HTTP_ENABLED with REDIS_URL needs the peer package `redis` in your application (npm install redis@3). Falling back to in-process HTTP counters. @adalo/metrics does not bundle redis.'\n )\n httpMetricsRedisAggregation = false\n }\n\n const isWebCtx = isWebServingDynoContext(processTypeBeforeSuper)\n const webRedisRecordingOnly =\n Boolean(httpMetricsRedisAggregation) &&\n isWebCtx &&\n process.env.NODE_ENV === 'production'\n\n super({\n ...config,\n ...(webRedisRecordingOnly ? { includeNodeDefaultMetrics: false } : {}),\n })\n\n this.httpMetricsEnabled = httpMetricsEnabled\n this.httpMetricsRedisAggregation = httpMetricsRedisAggregation\n\n const redisKeyProcessType = isMetricsExporterProcessType(this.processType)\n ? 'web'\n : this.processType\n\n this._httpRedisStore =\n this.httpMetricsEnabled && this.httpMetricsRedisAggregation\n ? new HttpMetricsRedisStore({\n redisUrl,\n appName: this.appName,\n processType: redisKeyProcessType,\n })\n : null\n\n this._webRedisHttpRecordingOnly = Boolean(\n webRedisRecordingOnly && this._httpRedisStore\n )\n\n this.exportRuntimeGauges = !this._webRedisHttpRecordingOnly\n\n const wcParsed = parseInt(process.env.WEB_CONCURRENCY || '', 10)\n this._bootstrapWebConcurrency = Number.isFinite(wcParsed) ? wcParsed : 0\n this._bootstrapHostCpuCount = os.cpus().length\n\n if (this.httpMetricsRedisAggregation && redisUrl) {\n if (isMetricsExporterProcessType(this.processType)) {\n this.defaultLabelsWithoutDynoId = {\n app: this.appName,\n process_type: 'web',\n }\n } else if (!this._webRedisHttpRecordingOnly) {\n this.defaultLabelsWithoutDynoId = {\n app: this.appName,\n process_type: this.processType,\n }\n }\n }\n\n this._skippedPushWorkerLogged = false\n\n this._lastUsageMicros = 0\n this._lastCheckTime = Date.now()\n\n this._initDefaultMetrics()\n this._logMetricsBootstrap()\n }\n\n _logMetricsBootstrap = () => {\n if (!this.enabled) {\n return\n }\n const wc = process.env.WEB_CONCURRENCY || ''\n console.warn(\n `${this.prefixLogs} metrics bootstrap WEB_CONCURRENCY=${wc || '(unset)'} host_cpus=${this._bootstrapHostCpuCount} dyno=${process.env.DYNO || '(unset)'} redis_http=${this.httpMetricsRedisAggregation} web_redis_only=${this._webRedisHttpRecordingOnly}`\n )\n }\n\n get isWebRedisHttpRecordingOnly() {\n return Boolean(this._webRedisHttpRecordingOnly)\n }\n\n _initDefaultMetrics = () => {\n if (this.exportRuntimeGauges) {\n this.createGauge({\n name: 'app_process_cpu_usage_percent',\n help: 'Current CPU usage of the Node.js process in percent',\n updateFn: this.getCpuUsagePercent,\n })\n\n this.createGauge({\n name: 'app_available_cpu_count',\n help: 'How many CPU cores are available to this process',\n updateFn: this.getAvailableCPUs,\n })\n\n this.createGauge({\n name: 'app_container_memory_usage_bytes',\n help: 'Current container RAM usage from cgroup',\n updateFn: this.getContainerMemoryUsage,\n })\n\n this.createGauge({\n name: 'app_event_loop_lag_ms',\n help: 'Estimated event loop lag in milliseconds',\n updateFn: this.measureLag,\n })\n\n this.createGauge({\n name: 'app_container_memory_limit_bytes',\n help: 'Max RAM available to container from cgroup (memory.max)',\n updateFn: this.getContainerMemoryLimit,\n })\n\n this.createGauge({\n name: 'app_uptime_seconds',\n help: 'How long the process has been running',\n updateFn: process.uptime,\n })\n\n this.createGauge({\n name: 'app_bootstrap_web_concurrency',\n help: 'WEB_CONCURRENCY at process start (diagnostic; 0 if unset/invalid)',\n updateFn: () => this._bootstrapWebConcurrency,\n })\n\n this.createGauge({\n name: 'app_bootstrap_host_cpu_count',\n help: 'os.cpus().length at process start (diagnostic)',\n updateFn: () => this._bootstrapHostCpuCount,\n })\n }\n\n const registerHttpCounters =\n this.httpMetricsEnabled && !this._webRedisHttpRecordingOnly\n\n if (registerHttpCounters) {\n this.createCounter({\n name: 'app_requests_total',\n help: 'Total number of HTTP requests',\n labelNames: this.withDefaultLabelsWithoutDynoId([\n 'method',\n 'route',\n 'appId',\n 'databaseId',\n 'status_code',\n ]),\n useLabelsWithoutDynoId: true,\n })\n\n this.createCounter({\n name: 'app_requests_total_duration',\n help: 'Total duration of HTTP requests in milliseconds',\n labelNames: this.withDefaultLabelsWithoutDynoId([\n 'method',\n 'route',\n 'appId',\n 'databaseId',\n 'status_code',\n ]),\n useLabelsWithoutDynoId: true,\n })\n }\n }\n\n getCpuUsagePercent = () => {\n try {\n const stat = fs.readFileSync('/sys/fs/cgroup/cpu.stat', 'utf-8')\n const match = stat.match(/usage_usec (\\d+)/)\n if (!match) return 0\n\n const now = Date.now()\n const currentUsage = parseInt(match[1], 10)\n\n if (this._lastUsageMicros === 0) {\n this._lastUsageMicros = currentUsage\n this._lastCheckTime = now\n return 0\n }\n\n const deltaUsage = currentUsage - this._lastUsageMicros\n const deltaTime = now - this._lastCheckTime\n\n this._lastUsageMicros = currentUsage\n this._lastCheckTime = now\n\n return (deltaUsage / (deltaTime * 1000)) * 100\n } catch {\n return 0\n }\n }\n\n getAvailableCPUs() {\n try {\n const cpuMaxPath = '/sys/fs/cgroup/cpu.max'\n if (fs.existsSync(cpuMaxPath)) {\n const [quotaStr, periodStr] = fs\n .readFileSync(cpuMaxPath, 'utf8')\n .trim()\n .split(' ')\n if (quotaStr === 'max') return os.cpus().length\n return parseInt(quotaStr, 10) / parseInt(periodStr, 10)\n }\n return os.cpus().length\n } catch {\n return 1\n }\n }\n\n getContainerMemoryUsage() {\n try {\n return parseInt(\n fs.readFileSync('/sys/fs/cgroup/memory.current', 'utf-8').trim(),\n 10\n )\n } catch {\n return process.memoryUsage().rss\n }\n }\n\n getContainerMemoryLimit() {\n try {\n const path = '/sys/fs/cgroup/memory.max'\n if (fs.existsSync(path)) {\n const val = fs.readFileSync(path, 'utf-8').trim()\n if (val !== 'max') {\n const parsed = parseInt(val, 10)\n if (parsed && parsed < os.totalmem()) return parsed\n }\n }\n return os.totalmem()\n } catch {\n return os.totalmem()\n }\n }\n\n measureLag() {\n return new Promise(resolve => {\n const start = Date.now()\n setImmediate(() => resolve(Date.now() - start))\n })\n }\n\n trackHttpRequest({\n method,\n route,\n status_code,\n appId = '',\n databaseId = '',\n duration,\n }) {\n if (!this.httpMetricsEnabled) return\n\n if (this._httpRedisStore) {\n this._httpRedisStore.record(\n method,\n route,\n status_code,\n appId,\n databaseId,\n duration\n )\n return\n }\n\n this.countersFunctions?.app_requests_total({\n method,\n route,\n status_code,\n appId,\n databaseId,\n })\n this.countersFunctions?.app_requests_total_duration(\n {\n method,\n route,\n status_code,\n appId,\n databaseId,\n },\n duration\n )\n }\n\n /**\n * Start periodic push to VM-agent (`METRICS_PUSHGATEWAY_URL`). Interval defaults to `intervalSec` from config/env.\n * @param {number} [interval] Seconds between pushes; defaults to `this.intervalSec`\n * @param {() => void | Promise<void>} [customPushMetrics] Optional; replaces default push when provided\n * @returns {void}\n */\n startPush = (interval, customPushMetrics) => {\n if (this._webRedisHttpRecordingOnly) {\n return\n }\n if (!shouldRunMetricsPush(this)) {\n if (\n this.enabled &&\n !this._skippedPushWorkerLogged &&\n process.env.METRICS_SUPPRESS_SKIP_PUSH_LOG !== 'true'\n ) {\n console.warn(\n `${this.prefixLogs} Skipping VM-agent push on this worker. METRICS_PUSH_ALL_WORKERS=true restores per-worker push.`\n )\n this._skippedPushWorkerLogged = true\n }\n return\n }\n this._startPush(interval, customPushMetrics)\n }\n\n async pushMetrics() {\n if (this._webRedisHttpRecordingOnly) {\n return\n }\n if (\n this._httpRedisStore &&\n shouldRunMetricsPush(this) &&\n this.countersFunctions?.app_requests_total &&\n this.countersFunctions?.app_requests_total_duration\n ) {\n await this._httpRedisStore.flushToCounters(\n (labels, value) =>\n this.countersFunctions.app_requests_total(labels, value),\n (labels, value) =>\n this.countersFunctions.app_requests_total_duration(labels, value)\n )\n }\n // eslint-disable-next-line consistent-return\n return super.pushMetrics()\n }\n\n trackHttpRequestMiddleware = (req, res, next) => {\n if (!this.enabled || !this.httpMetricsEnabled || req.method === 'OPTIONS') {\n next()\n return\n }\n\n const start = Date.now()\n res.on('finish', () => {\n const route = req.route?.path || req.path || 'unknown'\n const appId =\n req.params?.appId || req.body?.appId || req.query?.appId || ''\n const databaseId =\n req.params?.databaseId ||\n req.body?.databaseId ||\n req.query?.databaseId ||\n req.params?.datasourceId ||\n req.body?.datasourceId ||\n req.query?.datasourceId ||\n ''\n\n this.trackHttpRequest({\n method: req.method,\n route,\n status_code: res.statusCode,\n appId,\n databaseId,\n duration: Date.now() - start,\n })\n })\n\n next()\n }\n}\n\nmodule.exports = { MetricsClient }\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -37,7 +37,21 @@ function isMetricsExporterProcessType(processType) {
|
|
|
37
37
|
class MetricsClient extends BaseMetricsClient {
|
|
38
38
|
/**
|
|
39
39
|
* @param {Object} [config]
|
|
40
|
-
* @param {
|
|
40
|
+
* @param {string} [config.appName] Name of the application
|
|
41
|
+
* @param {string} [config.dynoId] Dyno/instance ID
|
|
42
|
+
* @param {string} [config.processType] Process type (web, worker, metrics, etc.)
|
|
43
|
+
* @param {boolean} [config.enabled] Enable metrics collection
|
|
44
|
+
* @param {boolean} [config.httpMetricsEnabled] Enable HTTP request metrics (app_requests_total, app_requests_total_duration); defaults from METRICS_HTTP_ENABLED
|
|
45
|
+
* @param {boolean} [config.logValues] Log metrics values to console
|
|
46
|
+
* @param {string} [config.pushgatewayUrl] Push URL (VM-agent import endpoint)
|
|
47
|
+
* @param {string} [config.pushgatewaySecret] Basic auth secret (Base64 user:password)
|
|
48
|
+
* @param {number} [config.intervalSec] Interval in seconds for pushing metrics
|
|
49
|
+
* @param {boolean} [config.removeOldMetrics] Enable to clear metrics by service name
|
|
50
|
+
* @param {function} [config.startupValidation] Add to validate on start push
|
|
51
|
+
* @param {boolean} [config.disablePushgateway] Disable pushing to VM-agent (use HTTP scraping instead)
|
|
52
|
+
* @param {boolean} [config.includeNodeDefaultMetrics] Register prom-client default process metrics
|
|
53
|
+
* @param {string} [config.httpMetricsRedisUrl] Overrides METRICS_HTTP_REDIS_URL / REDIS_URL for the HTTP Redis store
|
|
54
|
+
* @param {boolean} [config.httpMetricsRedisAggregation] When unset, on if Redis + HTTP metrics; set false to force in-process HTTP counters only
|
|
41
55
|
*/
|
|
42
56
|
constructor(config = {}) {
|
|
43
57
|
const processTypeBeforeSuper =
|
|
@@ -342,6 +356,12 @@ class MetricsClient extends BaseMetricsClient {
|
|
|
342
356
|
)
|
|
343
357
|
}
|
|
344
358
|
|
|
359
|
+
/**
|
|
360
|
+
* Start periodic push to VM-agent (`METRICS_PUSHGATEWAY_URL`). Interval defaults to `intervalSec` from config/env.
|
|
361
|
+
* @param {number} [interval] Seconds between pushes; defaults to `this.intervalSec`
|
|
362
|
+
* @param {() => void | Promise<void>} [customPushMetrics] Optional; replaces default push when provided
|
|
363
|
+
* @returns {void}
|
|
364
|
+
*/
|
|
345
365
|
startPush = (interval, customPushMetrics) => {
|
|
346
366
|
if (this._webRedisHttpRecordingOnly) {
|
|
347
367
|
return
|
|
@@ -362,7 +382,7 @@ class MetricsClient extends BaseMetricsClient {
|
|
|
362
382
|
this._startPush(interval, customPushMetrics)
|
|
363
383
|
}
|
|
364
384
|
|
|
365
|
-
|
|
385
|
+
async pushMetrics() {
|
|
366
386
|
if (this._webRedisHttpRecordingOnly) {
|
|
367
387
|
return
|
|
368
388
|
}
|
|
@@ -379,7 +399,8 @@ class MetricsClient extends BaseMetricsClient {
|
|
|
379
399
|
this.countersFunctions.app_requests_total_duration(labels, value)
|
|
380
400
|
)
|
|
381
401
|
}
|
|
382
|
-
return
|
|
402
|
+
// eslint-disable-next-line consistent-return
|
|
403
|
+
return super.pushMetrics()
|
|
383
404
|
}
|
|
384
405
|
|
|
385
406
|
trackHttpRequestMiddleware = (req, res, next) => {
|