@adalo/metrics 0.1.5 → 0.1.7
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/lib/metricsClient.d.ts +4 -1
- package/lib/metricsClient.d.ts.map +1 -1
- package/lib/metricsClient.js +16 -8
- package/lib/metricsClient.js.map +1 -1
- package/package.json +1 -1
- package/src/metricsClient.js +17 -8
- package/tsconfig.json +1 -1
package/lib/metricsClient.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export class MetricsClient {
|
|
|
14
14
|
* @param {string} [config.pushgatewayUser] PushGateway username
|
|
15
15
|
* @param {string} [config.pushgatewayPassword] PushGateway password
|
|
16
16
|
* @param {number} [config.intervalSec] Interval in seconds for pushing metrics
|
|
17
|
+
* @param {number} [config.removeAllJobs] Enable to clear all jobs at startup
|
|
17
18
|
*/
|
|
18
19
|
constructor(config?: {
|
|
19
20
|
appName?: string | undefined;
|
|
@@ -25,6 +26,7 @@ export class MetricsClient {
|
|
|
25
26
|
pushgatewayUser?: string | undefined;
|
|
26
27
|
pushgatewayPassword?: string | undefined;
|
|
27
28
|
intervalSec?: number | undefined;
|
|
29
|
+
removeAllJobs?: number | undefined;
|
|
28
30
|
});
|
|
29
31
|
appName: string;
|
|
30
32
|
dynoId: string;
|
|
@@ -42,6 +44,7 @@ export class MetricsClient {
|
|
|
42
44
|
dyno_id: string;
|
|
43
45
|
process_type: string;
|
|
44
46
|
};
|
|
47
|
+
authToken: string;
|
|
45
48
|
gateway: client.Pushgateway<"text/plain; version=0.0.4; charset=utf-8">;
|
|
46
49
|
gauges: {};
|
|
47
50
|
counters: {};
|
|
@@ -114,7 +117,7 @@ export class MetricsClient {
|
|
|
114
117
|
*/
|
|
115
118
|
startPush: (interval?: number | undefined) => void;
|
|
116
119
|
cleanup: () => Promise<never>;
|
|
117
|
-
_clearOldWorkers: () => Promise<void>;
|
|
120
|
+
_clearOldWorkers: (removeAllJobs: any) => Promise<void>;
|
|
118
121
|
_setCleanupHandlers: () => void;
|
|
119
122
|
}
|
|
120
123
|
import client = require("prom-client");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metricsClient.d.ts","sourceRoot":"","sources":["../src/metricsClient.js"],"names":[],"mappings":"AAKA;;;GAGG;AACH;IACE
|
|
1
|
+
{"version":3,"file":"metricsClient.d.ts","sourceRoot":"","sources":["../src/metricsClient.js"],"names":[],"mappings":"AAKA;;;GAGG;AACH;IACE;;;;;;;;;;;;OAYG;IACH;QAX2B,OAAO;QACP,MAAM;QACN,WAAW;QACV,OAAO;QACP,SAAS;QACV,cAAc;QACd,eAAe;QACf,mBAAmB;QACnB,WAAW;QACX,aAAa;OA4DvC;IAzDC,gBACiE;IACjE,eAAqE;IACrE,oBAG6B;IAC7B,iBAAuE;IACvE,mBAC+D;IAC/D,uBACoE;IACpE,wBACsE;IACtE,4BAGI;IACJ,oBAGI;IAEJ,mBAAyF;IAEzF,sEAAqC;IAGrC;;;;MAIC;IAED,kBAEoB;IACpB,wEAOC;IAED,WAAgB;IAChB,aAAkB;IAElB,mEAAmE;IACnE;YADkB,MAAM,SAAc,MAAM,GAAG,QAAQ,MAAM,CAAC;MACvC;IACvB,yBAAyB;IACzB,uBAAgC;IAOlC;;;OAGG;IACH,4BA8CC;IAED;;;;;;;OAOG;IACH,oBANW,MAAM,QACN,MAAM,oBACM,MAAM,GAAC,QAAQ,MAAM,CAAC,qDAEhC,OAAO,KAAK,CAqBxB;IAED;;;;;;;OAOG;IACH,oBALW,MAAM,QACN,MAAM,gEAEY,MAAM,4BAAU,MAAM,KAAG,IAAI,CAmBzD;IAED;;;OAGG;IACH,0BAFa,MAAM,CA2BlB;IAED;;;OAGG;IACH,oBAFa,MAAM,CAiBlB;IAED;;;OAGG;IACH,2BAFa,MAAM,CAWlB;IAED;;;OAGG;IACH,2BAFa,MAAM,CAgBlB;IAED;;;OAGG;IACH,cAFa,QAAQ,MAAM,CAAC,CAO3B;IAED;;;OAGG;IACH,oEA0BC;IAED;;OAEG;IACH,iCAgCC;IAED;;;OAGG;IACH,mDAYC;IAED,8BAWC;IAED,wDAiBC;IAED,gCAGC;CACF"}
|
package/lib/metricsClient.js
CHANGED
|
@@ -21,6 +21,7 @@ class MetricsClient {
|
|
|
21
21
|
* @param {string} [config.pushgatewayUser] PushGateway username
|
|
22
22
|
* @param {string} [config.pushgatewayPassword] PushGateway password
|
|
23
23
|
* @param {number} [config.intervalSec] Interval in seconds for pushing metrics
|
|
24
|
+
* @param {number} [config.removeAllJobs] Enable to clear all jobs at startup
|
|
24
25
|
*/
|
|
25
26
|
constructor(config = {}) {
|
|
26
27
|
this.appName = config.appName || process.env.METRICS_APP_NAME || 'unknown-app';
|
|
@@ -42,10 +43,10 @@ class MetricsClient {
|
|
|
42
43
|
dyno_id: this.dynoId,
|
|
43
44
|
process_type: this.processType
|
|
44
45
|
};
|
|
45
|
-
|
|
46
|
+
this.authToken = Buffer.from(`${this.pushgatewayUser}:${this.pushgatewayPassword}`).toString('base64');
|
|
46
47
|
this.gateway = new client.Pushgateway(this.pushgatewayUrl, {
|
|
47
48
|
headers: {
|
|
48
|
-
Authorization: `Basic ${authToken}`
|
|
49
|
+
Authorization: `Basic ${this.authToken}`
|
|
49
50
|
},
|
|
50
51
|
agent: new https.Agent({
|
|
51
52
|
keepAlive: true
|
|
@@ -58,7 +59,7 @@ class MetricsClient {
|
|
|
58
59
|
this.gaugeUpdaters = {};
|
|
59
60
|
this._lastUsageMicros = 0;
|
|
60
61
|
this._lastCheckTime = Date.now();
|
|
61
|
-
this._clearOldWorkers().then(_ => {
|
|
62
|
+
this._clearOldWorkers(config.removeAllJobs).then(_ => {
|
|
62
63
|
this._initDefaultMetrics();
|
|
63
64
|
this._setCleanupHandlers();
|
|
64
65
|
});
|
|
@@ -294,14 +295,21 @@ class MetricsClient {
|
|
|
294
295
|
}
|
|
295
296
|
process.exit(0);
|
|
296
297
|
};
|
|
297
|
-
_clearOldWorkers = async
|
|
298
|
+
_clearOldWorkers = async removeAllJobs => {
|
|
299
|
+
if (!removeAllJobs) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
const url = `${this.pushgatewayUrl}/api/v1/metrics/job/${this.appName}`;
|
|
298
303
|
try {
|
|
299
|
-
await
|
|
300
|
-
|
|
304
|
+
const res = await fetch(url, {
|
|
305
|
+
method: 'DELETE',
|
|
306
|
+
headers: {
|
|
307
|
+
Authorization: `Basic ${this.authToken}`
|
|
308
|
+
}
|
|
301
309
|
});
|
|
302
|
-
console.
|
|
310
|
+
if (res.ok) console.log('Deleted all instances for job', this.appName);else console.error('Failed to delete:', res.status, await res.text());
|
|
303
311
|
} catch (err) {
|
|
304
|
-
console.error(
|
|
312
|
+
console.error('Error deleting old metrics:', err);
|
|
305
313
|
}
|
|
306
314
|
};
|
|
307
315
|
_setCleanupHandlers = () => {
|
package/lib/metricsClient.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metricsClient.js","names":["client","require","fs","os","https","MetricsClient","constructor","config","appName","process","env","METRICS_APP_NAME","dynoId","HOSTNAME","processType","BUILD_DYNO_PROCESS_TYPE","enabled","METRICS_ENABLED","logValues","METRICS_LOG_VALUES","pushgatewayUrl","METRICS_PUSHGATEWAY_URL","pushgatewayUser","METRICS_PUSHGATEWAY_USER","pushgatewayPassword","METRICS_PUSHGATEWAY_PASSWORD","intervalSec","parseInt","METRICS_INTERVAL_SEC","prefixLogs","registry","Registry","collectDefaultMetrics","register","defaultLabels","app","dyno_id","process_type","authToken","Buffer","from","toString","gateway","Pushgateway","headers","Authorization","agent","Agent","keepAlive","gauges","counters","gaugeUpdaters","_lastUsageMicros","_lastCheckTime","Date","now","_clearOldWorkers","then","_","_initDefaultMetrics","_setCleanupHandlers","createGauge","getCpuUsagePercent","getAvailableCPUs","getContainerMemoryUsage","measureLag","getContainerMemoryLimit","uptime","createCounter","Object","keys","name","help","updateFn","labelNames","g","Gauge","registers","triggerFn","c","Counter","data","value","inc","stat","readFileSync","match","currentUsage","deltaUsage","deltaTime","cpuMaxPath","existsSync","quotaStr","periodStr","trim","split","cpus","length","memoryUsage","rss","path","val","parsed","totalmem","Promise","resolve","start","setImmediate","countHttpRequestMiddleware","req","res","next","on","route","appId","params","body","query","databaseId","app_http_requests_total","method","status_code","statusCode","duration","requestSize","pushMetrics","entries","result","undefined","set","err","console","error","push","jobName","groupings","instance","values","forEach","counter","reset","metrics","getMetricsAsJSON","log","JSON","stringify","startPush","interval","warn","setInterval","catch","cleanup","delete","exit","module","exports"],"sources":["../src/metricsClient.js"],"sourcesContent":["const client = require('prom-client')\nconst fs = require('fs')\nconst os = require('os')\nconst https = require('https')\n\n/**\n * MetricsClient handles Prometheus metrics collection and push.\n * Supports gauges, counters, default metrics, and custom metrics.\n */\nclass MetricsClient {\n /**\n * @param {Object} config\n * @param {string} [config.appName] Name of the application\n * @param {string} [config.dynoId] Dyno/instance ID\n * @param {string} [config.processType] Process type (web, worker, etc.)\n * @param {boolean} [config.enabled] Enable metrics collection\n * @param {boolean} [config.logValues] Log metrics values to console\n * @param {string} [config.pushgatewayUrl] PushGateway URL\n * @param {string} [config.pushgatewayUser] PushGateway username\n * @param {string} [config.pushgatewayPassword] PushGateway password\n * @param {number} [config.intervalSec] Interval in seconds for pushing metrics\n */\n constructor(config = {}) {\n this.appName =\n config.appName || process.env.METRICS_APP_NAME || 'unknown-app'\n this.dynoId = config.dynoId || process.env.HOSTNAME || 'unknown-dyno'\n this.processType =\n config.processType ||\n process.env.BUILD_DYNO_PROCESS_TYPE ||\n 'undefined_build_dyno_type'\n this.enabled = config.enabled ?? process.env.METRICS_ENABLED === 'true'\n this.logValues =\n config.logValues ?? process.env.METRICS_LOG_VALUES === 'true'\n this.pushgatewayUrl =\n config.pushgatewayUrl || process.env.METRICS_PUSHGATEWAY_URL || ''\n this.pushgatewayUser =\n config.pushgatewayUser || process.env.METRICS_PUSHGATEWAY_USER || ''\n this.pushgatewayPassword =\n config.pushgatewayPassword ||\n process.env.METRICS_PUSHGATEWAY_PASSWORD ||\n ''\n this.intervalSec =\n config.intervalSec ||\n parseInt(process.env.METRICS_INTERVAL_SEC || '', 10) ||\n 15\n\n this.prefixLogs = `[${this.processType}] [${this.appName}] [${this.dynoId}] [Monitoring]`\n\n this.registry = new client.Registry()\n client.collectDefaultMetrics({ register: this.registry })\n\n this.defaultLabels = {\n app: this.appName,\n dyno_id: this.dynoId,\n process_type: this.processType,\n }\n\n const authToken = Buffer.from(\n `${this.pushgatewayUser}:${this.pushgatewayPassword}`\n ).toString('base64')\n this.gateway = new client.Pushgateway(\n this.pushgatewayUrl,\n {\n headers: { Authorization: `Basic ${authToken}` },\n agent: new https.Agent({ keepAlive: true }),\n },\n this.registry\n )\n\n this.gauges = {}\n this.counters = {}\n\n /** @type {Object<string, function(): number | Promise<number>>} */\n this.gaugeUpdaters = {}\n this._lastUsageMicros = 0\n this._lastCheckTime = Date.now()\n this._clearOldWorkers().then(_ => {\n this._initDefaultMetrics()\n this._setCleanupHandlers()\n })\n }\n\n /**\n * Register default gauges and counters.\n * @private\n */\n _initDefaultMetrics = () => {\n this.createGauge(\n 'app_process_cpu_usage_percent',\n 'Current CPU usage of the Node.js process in percent',\n this.getCpuUsagePercent\n )\n this.createGauge(\n 'app_available_cpu_count',\n 'How many CPU cores are available to this process',\n this.getAvailableCPUs\n )\n this.createGauge(\n 'app_container_memory_usage_bytes',\n 'Current container RAM usage from cgroup',\n this.getContainerMemoryUsage\n )\n this.createGauge(\n 'app_event_loop_lag_ms',\n 'Estimated event loop lag in milliseconds',\n this.measureLag\n )\n this.createGauge(\n 'app_container_memory_limit_bytes',\n 'Max RAM available to container from cgroup (memory.max)',\n this.getContainerMemoryLimit\n )\n this.createGauge(\n 'app_uptime_seconds',\n 'How long the process has been running',\n process.uptime\n )\n\n this.createCounter(\n 'app_http_requests_total',\n 'Total number of HTTP requests handled by this process',\n [\n ...Object.keys(this.defaultLabels),\n 'method',\n 'route',\n 'appId',\n 'databaseId',\n 'duration',\n 'requestSize',\n 'status_code',\n ]\n )\n }\n\n /**\n * Create a gauge metric.\n * @param {string} name\n * @param {string} help\n * @param {function(): number|Promise<number>} [updateFn] Optional function returning value\n * @param {string[]} [labelNames]\n * @returns {client.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 (typeof updateFn === 'function') this.gaugeUpdaters[name] = updateFn\n\n return g\n }\n\n /**\n * Create a counter metric.\n * Returns a trigger function to increment the counter manually.\n * @param {string} name\n * @param {string} help\n * @param {string[]} [labelNames]\n * @returns {function(data?: object, value?: number): void} triggerFn\n */\n createCounter(name, help, labelNames = Object.keys(this.defaultLabels)) {\n if (this.counters[name]) return this.counters[name].triggerFn\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 const triggerFn = (data = {}, value = 1) => {\n c.inc({ ...this.defaultLabels, ...data }, value)\n }\n\n this.counters[name].triggerFn = triggerFn\n return triggerFn\n }\n\n /**\n * Get CPU usage percent (cgroup-aware)\n * @returns {number}\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 /**\n * Get available CPU cores.\n * @returns {number}\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 /**\n * Get container memory usage in bytes.\n * @returns {number}\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 /**\n * Get container memory limit in bytes.\n * @returns {number}\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 /**\n * Measure event loop lag in ms.\n * @returns {Promise<number>}\n */\n measureLag() {\n return new Promise(resolve => {\n const start = Date.now()\n setImmediate(() => resolve(Date.now() - start))\n })\n }\n\n /**\n * Express middleware to count HTTP requests.\n * Increments the `app_http_requests_total` counter.\n */\n countHttpRequestMiddleware = (req, res, next) => {\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 ''\n\n this.counters?.app_http_requests_total?.triggerFn({\n method: req.method,\n route,\n status_code: res.statusCode,\n appId,\n databaseId,\n duration: Date.now() - start,\n requestSize: req.headers['content-length']\n ? parseInt(req.headers['content-length'], 10)\n : 0,\n })\n })\n\n next()\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 const result = updateFn()\n const val = result instanceof Promise ? await result : result\n if (val !== undefined) this.gauges[name].set(this.defaultLabels, val)\n } catch (err) {\n console.error(\n `${this.prefixLogs} Failed to update gauge ${name}:`,\n err\n )\n }\n }\n\n await this.gateway.push({\n jobName: this.appName,\n groupings: { process_type: this.processType, instance: this.dynoId },\n })\n\n Object.values(this.counters).forEach(counter => counter.reset())\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 /**\n * Start automatic periodic push of metrics.\n * @param {number} [interval] Interval in seconds\n */\n startPush = (interval = this.intervalSec) => {\n if (!this.enabled) {\n console.warn(`${this.prefixLogs} Metrics disabled`)\n }\n\n setInterval(() => {\n this.pushMetrics().catch(err => {\n console.error(`${this.prefixLogs} Failed to push metrics:`, err)\n })\n }, interval * 1000)\n\n console.warn(`${this.prefixLogs} Metrics collection started.`)\n }\n\n cleanup = async () => {\n if (this.enabled) {\n await this.gateway.delete({\n jobName: this.appName,\n groupings: {\n process_type: this.processType,\n instance: this.dynoId,\n },\n })\n }\n process.exit(0)\n }\n\n _clearOldWorkers = async () => {\n try {\n await this.gateway.delete({\n jobName: this.appName,\n })\n console.warn(`${this.prefixLogs} Cleared all old workers metrics.`)\n } catch (err) {\n console.error(`${this.prefixLogs} Failed to clear old metrics:`, err)\n }\n }\n\n _setCleanupHandlers = () => {\n process.on('SIGINT', this.cleanup)\n process.on('SIGTERM', this.cleanup)\n }\n}\n\nmodule.exports = { MetricsClient }\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"metricsClient.js","names":["client","require","fs","os","https","MetricsClient","constructor","config","appName","process","env","METRICS_APP_NAME","dynoId","HOSTNAME","processType","BUILD_DYNO_PROCESS_TYPE","enabled","METRICS_ENABLED","logValues","METRICS_LOG_VALUES","pushgatewayUrl","METRICS_PUSHGATEWAY_URL","pushgatewayUser","METRICS_PUSHGATEWAY_USER","pushgatewayPassword","METRICS_PUSHGATEWAY_PASSWORD","intervalSec","parseInt","METRICS_INTERVAL_SEC","prefixLogs","registry","Registry","collectDefaultMetrics","register","defaultLabels","app","dyno_id","process_type","authToken","Buffer","from","toString","gateway","Pushgateway","headers","Authorization","agent","Agent","keepAlive","gauges","counters","gaugeUpdaters","_lastUsageMicros","_lastCheckTime","Date","now","_clearOldWorkers","removeAllJobs","then","_","_initDefaultMetrics","_setCleanupHandlers","createGauge","getCpuUsagePercent","getAvailableCPUs","getContainerMemoryUsage","measureLag","getContainerMemoryLimit","uptime","createCounter","Object","keys","name","help","updateFn","labelNames","g","Gauge","registers","triggerFn","c","Counter","data","value","inc","stat","readFileSync","match","currentUsage","deltaUsage","deltaTime","cpuMaxPath","existsSync","quotaStr","periodStr","trim","split","cpus","length","memoryUsage","rss","path","val","parsed","totalmem","Promise","resolve","start","setImmediate","countHttpRequestMiddleware","req","res","next","on","route","appId","params","body","query","databaseId","app_http_requests_total","method","status_code","statusCode","duration","requestSize","pushMetrics","entries","result","undefined","set","err","console","error","push","jobName","groupings","instance","values","forEach","counter","reset","metrics","getMetricsAsJSON","log","JSON","stringify","startPush","interval","warn","setInterval","catch","cleanup","delete","exit","url","fetch","ok","status","text","module","exports"],"sources":["../src/metricsClient.js"],"sourcesContent":["const client = require('prom-client')\nconst fs = require('fs')\nconst os = require('os')\nconst https = require('https')\n\n/**\n * MetricsClient handles Prometheus metrics collection and push.\n * Supports gauges, counters, default metrics, and custom metrics.\n */\nclass MetricsClient {\n /**\n * @param {Object} config\n * @param {string} [config.appName] Name of the application\n * @param {string} [config.dynoId] Dyno/instance ID\n * @param {string} [config.processType] Process type (web, worker, etc.)\n * @param {boolean} [config.enabled] Enable metrics collection\n * @param {boolean} [config.logValues] Log metrics values to console\n * @param {string} [config.pushgatewayUrl] PushGateway URL\n * @param {string} [config.pushgatewayUser] PushGateway username\n * @param {string} [config.pushgatewayPassword] PushGateway password\n * @param {number} [config.intervalSec] Interval in seconds for pushing metrics\n * @param {number} [config.removeAllJobs] Enable to clear all jobs at startup\n */\n constructor(config = {}) {\n this.appName =\n config.appName || process.env.METRICS_APP_NAME || 'unknown-app'\n this.dynoId = config.dynoId || process.env.HOSTNAME || 'unknown-dyno'\n this.processType =\n config.processType ||\n process.env.BUILD_DYNO_PROCESS_TYPE ||\n 'undefined_build_dyno_type'\n this.enabled = config.enabled ?? process.env.METRICS_ENABLED === 'true'\n this.logValues =\n config.logValues ?? process.env.METRICS_LOG_VALUES === 'true'\n this.pushgatewayUrl =\n config.pushgatewayUrl || process.env.METRICS_PUSHGATEWAY_URL || ''\n this.pushgatewayUser =\n config.pushgatewayUser || process.env.METRICS_PUSHGATEWAY_USER || ''\n this.pushgatewayPassword =\n config.pushgatewayPassword ||\n process.env.METRICS_PUSHGATEWAY_PASSWORD ||\n ''\n this.intervalSec =\n config.intervalSec ||\n parseInt(process.env.METRICS_INTERVAL_SEC || '', 10) ||\n 15\n\n this.prefixLogs = `[${this.processType}] [${this.appName}] [${this.dynoId}] [Monitoring]`\n\n this.registry = new client.Registry()\n client.collectDefaultMetrics({ register: this.registry })\n\n this.defaultLabels = {\n app: this.appName,\n dyno_id: this.dynoId,\n process_type: this.processType,\n }\n\n this.authToken = Buffer.from(\n `${this.pushgatewayUser}:${this.pushgatewayPassword}`\n ).toString('base64')\n this.gateway = new client.Pushgateway(\n this.pushgatewayUrl,\n {\n headers: { Authorization: `Basic ${this.authToken}` },\n agent: new https.Agent({ keepAlive: true }),\n },\n this.registry\n )\n\n this.gauges = {}\n this.counters = {}\n\n /** @type {Object<string, function(): number | Promise<number>>} */\n this.gaugeUpdaters = {}\n this._lastUsageMicros = 0\n this._lastCheckTime = Date.now()\n this._clearOldWorkers(config.removeAllJobs).then(_ => {\n this._initDefaultMetrics()\n this._setCleanupHandlers()\n })\n }\n\n /**\n * Register default gauges and counters.\n * @private\n */\n _initDefaultMetrics = () => {\n this.createGauge(\n 'app_process_cpu_usage_percent',\n 'Current CPU usage of the Node.js process in percent',\n this.getCpuUsagePercent\n )\n this.createGauge(\n 'app_available_cpu_count',\n 'How many CPU cores are available to this process',\n this.getAvailableCPUs\n )\n this.createGauge(\n 'app_container_memory_usage_bytes',\n 'Current container RAM usage from cgroup',\n this.getContainerMemoryUsage\n )\n this.createGauge(\n 'app_event_loop_lag_ms',\n 'Estimated event loop lag in milliseconds',\n this.measureLag\n )\n this.createGauge(\n 'app_container_memory_limit_bytes',\n 'Max RAM available to container from cgroup (memory.max)',\n this.getContainerMemoryLimit\n )\n this.createGauge(\n 'app_uptime_seconds',\n 'How long the process has been running',\n process.uptime\n )\n\n this.createCounter(\n 'app_http_requests_total',\n 'Total number of HTTP requests handled by this process',\n [\n ...Object.keys(this.defaultLabels),\n 'method',\n 'route',\n 'appId',\n 'databaseId',\n 'duration',\n 'requestSize',\n 'status_code',\n ]\n )\n }\n\n /**\n * Create a gauge metric.\n * @param {string} name\n * @param {string} help\n * @param {function(): number|Promise<number>} [updateFn] Optional function returning value\n * @param {string[]} [labelNames]\n * @returns {client.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 (typeof updateFn === 'function') this.gaugeUpdaters[name] = updateFn\n\n return g\n }\n\n /**\n * Create a counter metric.\n * Returns a trigger function to increment the counter manually.\n * @param {string} name\n * @param {string} help\n * @param {string[]} [labelNames]\n * @returns {function(data?: object, value?: number): void} triggerFn\n */\n createCounter(name, help, labelNames = Object.keys(this.defaultLabels)) {\n if (this.counters[name]) return this.counters[name].triggerFn\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 const triggerFn = (data = {}, value = 1) => {\n c.inc({ ...this.defaultLabels, ...data }, value)\n }\n\n this.counters[name].triggerFn = triggerFn\n return triggerFn\n }\n\n /**\n * Get CPU usage percent (cgroup-aware)\n * @returns {number}\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 /**\n * Get available CPU cores.\n * @returns {number}\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 /**\n * Get container memory usage in bytes.\n * @returns {number}\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 /**\n * Get container memory limit in bytes.\n * @returns {number}\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 /**\n * Measure event loop lag in ms.\n * @returns {Promise<number>}\n */\n measureLag() {\n return new Promise(resolve => {\n const start = Date.now()\n setImmediate(() => resolve(Date.now() - start))\n })\n }\n\n /**\n * Express middleware to count HTTP requests.\n * Increments the `app_http_requests_total` counter.\n */\n countHttpRequestMiddleware = (req, res, next) => {\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 ''\n\n this.counters?.app_http_requests_total?.triggerFn({\n method: req.method,\n route,\n status_code: res.statusCode,\n appId,\n databaseId,\n duration: Date.now() - start,\n requestSize: req.headers['content-length']\n ? parseInt(req.headers['content-length'], 10)\n : 0,\n })\n })\n\n next()\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 const result = updateFn()\n const val = result instanceof Promise ? await result : result\n if (val !== undefined) this.gauges[name].set(this.defaultLabels, val)\n } catch (err) {\n console.error(\n `${this.prefixLogs} Failed to update gauge ${name}:`,\n err\n )\n }\n }\n\n await this.gateway.push({\n jobName: this.appName,\n groupings: { process_type: this.processType, instance: this.dynoId },\n })\n\n Object.values(this.counters).forEach(counter => counter.reset())\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 /**\n * Start automatic periodic push of metrics.\n * @param {number} [interval] Interval in seconds\n */\n startPush = (interval = this.intervalSec) => {\n if (!this.enabled) {\n console.warn(`${this.prefixLogs} Metrics disabled`)\n }\n\n setInterval(() => {\n this.pushMetrics().catch(err => {\n console.error(`${this.prefixLogs} Failed to push metrics:`, err)\n })\n }, interval * 1000)\n\n console.warn(`${this.prefixLogs} Metrics collection started.`)\n }\n\n cleanup = async () => {\n if (this.enabled) {\n await this.gateway.delete({\n jobName: this.appName,\n groupings: {\n process_type: this.processType,\n instance: this.dynoId,\n },\n })\n }\n process.exit(0)\n }\n\n _clearOldWorkers = async removeAllJobs => {\n if (!removeAllJobs) {\n return\n }\n const url = `${this.pushgatewayUrl}/api/v1/metrics/job/${this.appName}`\n try {\n const res = await fetch(url, {\n method: 'DELETE',\n headers: {\n Authorization: `Basic ${this.authToken}`,\n },\n })\n if (res.ok) console.log('Deleted all instances for job', this.appName)\n else console.error('Failed to delete:', res.status, await res.text())\n } catch (err) {\n console.error('Error deleting old metrics:', err)\n }\n }\n\n _setCleanupHandlers = () => {\n process.on('SIGINT', this.cleanup)\n process.on('SIGTERM', this.cleanup)\n }\n}\n\nmodule.exports = { MetricsClient }\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
package/src/metricsClient.js
CHANGED
|
@@ -19,6 +19,7 @@ class MetricsClient {
|
|
|
19
19
|
* @param {string} [config.pushgatewayUser] PushGateway username
|
|
20
20
|
* @param {string} [config.pushgatewayPassword] PushGateway password
|
|
21
21
|
* @param {number} [config.intervalSec] Interval in seconds for pushing metrics
|
|
22
|
+
* @param {number} [config.removeAllJobs] Enable to clear all jobs at startup
|
|
22
23
|
*/
|
|
23
24
|
constructor(config = {}) {
|
|
24
25
|
this.appName =
|
|
@@ -55,13 +56,13 @@ class MetricsClient {
|
|
|
55
56
|
process_type: this.processType,
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
this.authToken = Buffer.from(
|
|
59
60
|
`${this.pushgatewayUser}:${this.pushgatewayPassword}`
|
|
60
61
|
).toString('base64')
|
|
61
62
|
this.gateway = new client.Pushgateway(
|
|
62
63
|
this.pushgatewayUrl,
|
|
63
64
|
{
|
|
64
|
-
headers: { Authorization: `Basic ${authToken}` },
|
|
65
|
+
headers: { Authorization: `Basic ${this.authToken}` },
|
|
65
66
|
agent: new https.Agent({ keepAlive: true }),
|
|
66
67
|
},
|
|
67
68
|
this.registry
|
|
@@ -74,7 +75,7 @@ class MetricsClient {
|
|
|
74
75
|
this.gaugeUpdaters = {}
|
|
75
76
|
this._lastUsageMicros = 0
|
|
76
77
|
this._lastCheckTime = Date.now()
|
|
77
|
-
this._clearOldWorkers().then(_ => {
|
|
78
|
+
this._clearOldWorkers(config.removeAllJobs).then(_ => {
|
|
78
79
|
this._initDefaultMetrics()
|
|
79
80
|
this._setCleanupHandlers()
|
|
80
81
|
})
|
|
@@ -386,14 +387,22 @@ class MetricsClient {
|
|
|
386
387
|
process.exit(0)
|
|
387
388
|
}
|
|
388
389
|
|
|
389
|
-
_clearOldWorkers = async
|
|
390
|
+
_clearOldWorkers = async removeAllJobs => {
|
|
391
|
+
if (!removeAllJobs) {
|
|
392
|
+
return
|
|
393
|
+
}
|
|
394
|
+
const url = `${this.pushgatewayUrl}/api/v1/metrics/job/${this.appName}`
|
|
390
395
|
try {
|
|
391
|
-
await
|
|
392
|
-
|
|
396
|
+
const res = await fetch(url, {
|
|
397
|
+
method: 'DELETE',
|
|
398
|
+
headers: {
|
|
399
|
+
Authorization: `Basic ${this.authToken}`,
|
|
400
|
+
},
|
|
393
401
|
})
|
|
394
|
-
console.
|
|
402
|
+
if (res.ok) console.log('Deleted all instances for job', this.appName)
|
|
403
|
+
else console.error('Failed to delete:', res.status, await res.text())
|
|
395
404
|
} catch (err) {
|
|
396
|
-
console.error(
|
|
405
|
+
console.error('Error deleting old metrics:', err)
|
|
397
406
|
}
|
|
398
407
|
}
|
|
399
408
|
|