@adalo/metrics 0.0.0-staging.13 → 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 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
- new MetricsClient({
30
- appName, // defaults: process.env.BUILD_APP_NAME || 'unknown-app'
31
- dynoId, // defaults: process.env.HOSTNAME || 'unknown-dyno'
32
- processType, // defaults: process.env.BUILD_DYNO_PROCESS_TYPE || 'undefined_build_dyno_type'
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
- pushMetrics: () => Promise<void>;
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,iCAEC;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"}
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
- pushMetrics = async () => {
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":"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","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":[]}
@@ -1 +1 @@
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;IAsBD,oEA+BC;CACF"}
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"}
@@ -286,15 +286,16 @@ class MetricsClient extends BaseMetricsClient {
286
286
  }
287
287
  this._startPush(interval, customPushMetrics);
288
288
  };
289
- pushMetrics = async () => {
289
+ async pushMetrics() {
290
290
  if (this._webRedisHttpRecordingOnly) {
291
291
  return;
292
292
  }
293
293
  if (this._httpRedisStore && shouldRunMetricsPush(this) && this.countersFunctions?.app_requests_total && this.countersFunctions?.app_requests_total_duration) {
294
294
  await this._httpRedisStore.flushToCounters((labels, value) => this.countersFunctions.app_requests_total(labels, value), (labels, value) => this.countersFunctions.app_requests_total_duration(labels, value));
295
295
  }
296
- return BaseMetricsClient.prototype.pushMetrics.call(this);
297
- };
296
+ // eslint-disable-next-line consistent-return
297
+ return super.pushMetrics();
298
+ }
298
299
  trackHttpRequestMiddleware = (req, res, next) => {
299
300
  if (!this.enabled || !this.httpMetricsEnabled || req.method === 'OPTIONS') {
300
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 {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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adalo/metrics",
3
- "version": "0.0.0-staging.13",
3
+ "version": "0.0.0-staging.14",
4
4
  "description": "Reusable metrics utilities for Node.js and Laravel apps",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -262,7 +262,8 @@ class BaseMetricsClient {
262
262
  )
263
263
  }
264
264
 
265
- pushMetrics = async () => {
265
+ /** Must be a prototype method (not a class field) so subclasses can `super.pushMetrics()`. */
266
+ async pushMetrics() {
266
267
  return this._pushMetrics()
267
268
  }
268
269
 
@@ -382,7 +382,7 @@ class MetricsClient extends BaseMetricsClient {
382
382
  this._startPush(interval, customPushMetrics)
383
383
  }
384
384
 
385
- pushMetrics = async () => {
385
+ async pushMetrics() {
386
386
  if (this._webRedisHttpRecordingOnly) {
387
387
  return
388
388
  }
@@ -399,7 +399,8 @@ class MetricsClient extends BaseMetricsClient {
399
399
  this.countersFunctions.app_requests_total_duration(labels, value)
400
400
  )
401
401
  }
402
- return BaseMetricsClient.prototype.pushMetrics.call(this)
402
+ // eslint-disable-next-line consistent-return
403
+ return super.pushMetrics()
403
404
  }
404
405
 
405
406
  trackHttpRequestMiddleware = (req, res, next) => {