@adalo/metrics 0.1.145 → 0.1.147
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/.env.example +1 -0
- package/.idea/codeStyles/Project.xml +101 -0
- package/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/git_toolbox_prj.xml +15 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/jsLibraryMappings.xml +6 -0
- package/.idea/prettier.xml +6 -0
- package/.idea/vcs.xml +6 -0
- package/README.md +3 -4
- package/lib/metrics/baseMetricsClient.d.ts +7 -1
- package/lib/metrics/baseMetricsClient.d.ts.map +1 -1
- package/lib/metrics/baseMetricsClient.js +50 -3
- package/lib/metrics/baseMetricsClient.js.map +1 -1
- package/package.json +1 -1
- package/src/metrics/baseMetricsClient.js +72 -5
package/.env.example
CHANGED
|
@@ -8,6 +8,7 @@ METRICS_LOG_VALUES=true
|
|
|
8
8
|
METRICS_PUSHGATEWAY_URL=https://vm-agent.infradalogs.adalo.com
|
|
9
9
|
METRICS_PUSHGATEWAY_SECRET="METRICS_PUSHGATEWAY_SECRET"
|
|
10
10
|
METRICS_INTERVAL_SEC=60
|
|
11
|
+
# METRICS_REMOVE_OLD_METRICS=false (set true to delete this instance's metrics from VM on exit)
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<component name="ProjectCodeStyleConfiguration">
|
|
2
|
+
<code_scheme name="Project" version="173">
|
|
3
|
+
<option name="OTHER_INDENT_OPTIONS">
|
|
4
|
+
<value>
|
|
5
|
+
<option name="INDENT_SIZE" value="2" />
|
|
6
|
+
<option name="TAB_SIZE" value="2" />
|
|
7
|
+
</value>
|
|
8
|
+
</option>
|
|
9
|
+
<HTMLCodeStyleSettings>
|
|
10
|
+
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
|
11
|
+
</HTMLCodeStyleSettings>
|
|
12
|
+
<JSCodeStyleSettings version="0">
|
|
13
|
+
<option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
|
|
14
|
+
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
|
15
|
+
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACKETS" value="true" />
|
|
16
|
+
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
|
17
|
+
<option name="USE_DOUBLE_QUOTES" value="false" />
|
|
18
|
+
<option name="FORCE_QUOTE_STYlE" value="true" />
|
|
19
|
+
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
|
|
20
|
+
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
|
21
|
+
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
|
22
|
+
<option name="SPACES_WITHIN_INTERPOLATION_EXPRESSIONS" value="true" />
|
|
23
|
+
</JSCodeStyleSettings>
|
|
24
|
+
<TypeScriptCodeStyleSettings version="0">
|
|
25
|
+
<option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
|
|
26
|
+
<option name="FORCE_SEMICOLON_STYLE" value="true" />
|
|
27
|
+
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
|
|
28
|
+
<option name="USE_DOUBLE_QUOTES" value="false" />
|
|
29
|
+
<option name="FORCE_QUOTE_STYlE" value="true" />
|
|
30
|
+
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
|
|
31
|
+
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
|
32
|
+
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
|
33
|
+
</TypeScriptCodeStyleSettings>
|
|
34
|
+
<VueCodeStyleSettings>
|
|
35
|
+
<option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
|
|
36
|
+
<option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
|
|
37
|
+
</VueCodeStyleSettings>
|
|
38
|
+
<codeStyleSettings language="CSS">
|
|
39
|
+
<indentOptions>
|
|
40
|
+
<option name="INDENT_SIZE" value="2" />
|
|
41
|
+
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
|
42
|
+
<option name="TAB_SIZE" value="2" />
|
|
43
|
+
</indentOptions>
|
|
44
|
+
</codeStyleSettings>
|
|
45
|
+
<codeStyleSettings language="Gherkin">
|
|
46
|
+
<indentOptions>
|
|
47
|
+
<option name="TAB_SIZE" value="2" />
|
|
48
|
+
</indentOptions>
|
|
49
|
+
</codeStyleSettings>
|
|
50
|
+
<codeStyleSettings language="HTML">
|
|
51
|
+
<option name="SOFT_MARGINS" value="80" />
|
|
52
|
+
<indentOptions>
|
|
53
|
+
<option name="INDENT_SIZE" value="2" />
|
|
54
|
+
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
|
55
|
+
<option name="TAB_SIZE" value="2" />
|
|
56
|
+
</indentOptions>
|
|
57
|
+
</codeStyleSettings>
|
|
58
|
+
<codeStyleSettings language="JSON">
|
|
59
|
+
<indentOptions>
|
|
60
|
+
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
|
61
|
+
</indentOptions>
|
|
62
|
+
</codeStyleSettings>
|
|
63
|
+
<codeStyleSettings language="JavaScript">
|
|
64
|
+
<option name="BLOCK_COMMENT_ADD_SPACE" value="true" />
|
|
65
|
+
<option name="IF_BRACE_FORCE" value="1" />
|
|
66
|
+
<option name="DOWHILE_BRACE_FORCE" value="1" />
|
|
67
|
+
<option name="WHILE_BRACE_FORCE" value="1" />
|
|
68
|
+
<option name="FOR_BRACE_FORCE" value="1" />
|
|
69
|
+
<option name="SOFT_MARGINS" value="80" />
|
|
70
|
+
<indentOptions>
|
|
71
|
+
<option name="INDENT_SIZE" value="2" />
|
|
72
|
+
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
|
73
|
+
<option name="TAB_SIZE" value="2" />
|
|
74
|
+
</indentOptions>
|
|
75
|
+
</codeStyleSettings>
|
|
76
|
+
<codeStyleSettings language="LESS">
|
|
77
|
+
<indentOptions>
|
|
78
|
+
<option name="TAB_SIZE" value="2" />
|
|
79
|
+
</indentOptions>
|
|
80
|
+
</codeStyleSettings>
|
|
81
|
+
<codeStyleSettings language="TypeScript">
|
|
82
|
+
<option name="BLOCK_COMMENT_ADD_SPACE" value="true" />
|
|
83
|
+
<option name="IF_BRACE_FORCE" value="1" />
|
|
84
|
+
<option name="DOWHILE_BRACE_FORCE" value="1" />
|
|
85
|
+
<option name="WHILE_BRACE_FORCE" value="1" />
|
|
86
|
+
<option name="FOR_BRACE_FORCE" value="1" />
|
|
87
|
+
<option name="SOFT_MARGINS" value="80" />
|
|
88
|
+
<indentOptions>
|
|
89
|
+
<option name="INDENT_SIZE" value="2" />
|
|
90
|
+
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
|
91
|
+
<option name="TAB_SIZE" value="2" />
|
|
92
|
+
</indentOptions>
|
|
93
|
+
</codeStyleSettings>
|
|
94
|
+
<codeStyleSettings language="Vue">
|
|
95
|
+
<option name="SOFT_MARGINS" value="80" />
|
|
96
|
+
<indentOptions>
|
|
97
|
+
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
|
98
|
+
</indentOptions>
|
|
99
|
+
</codeStyleSettings>
|
|
100
|
+
</code_scheme>
|
|
101
|
+
</component>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="GitToolBoxProjectSettings">
|
|
4
|
+
<option name="commitMessageIssueKeyValidationOverride">
|
|
5
|
+
<BoolValueOverride>
|
|
6
|
+
<option name="enabled" value="true" />
|
|
7
|
+
</BoolValueOverride>
|
|
8
|
+
</option>
|
|
9
|
+
<option name="commitMessageValidationEnabledOverride">
|
|
10
|
+
<BoolValueOverride>
|
|
11
|
+
<option name="enabled" value="true" />
|
|
12
|
+
</BoolValueOverride>
|
|
13
|
+
</option>
|
|
14
|
+
</component>
|
|
15
|
+
</project>
|
package/.idea/vcs.xml
ADDED
package/README.md
CHANGED
|
@@ -10,9 +10,8 @@ new MetricsClient({
|
|
|
10
10
|
enabled, // defaults: process.env.METRICS_ENABLED === 'true'
|
|
11
11
|
logValues, // defaults: process.env.METRICS_LOG_VALUES === 'true'
|
|
12
12
|
pushgatewayUrl, // defaults: process.env.METRICS_PUSHGATEWAY_URL || ''
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
intervalSec // defaults: process.env.METRICS_INTERVAL_SEC || 15
|
|
13
|
+
pushgatewaySecret, // defaults: process.env.METRICS_PUSHGATEWAY_SECRET || '' (Base64 of user:password)
|
|
14
|
+
intervalSec, // defaults: process.env.METRICS_INTERVAL_SEC || 15
|
|
16
15
|
})
|
|
17
16
|
```
|
|
18
17
|
## Example Usage
|
|
@@ -44,7 +43,7 @@ const testGauge = metricsClient.createGauge({
|
|
|
44
43
|
// Push metrics manually
|
|
45
44
|
metricsClient.gatewayPush({ groupings: { process_type: 'web' } })
|
|
46
45
|
|
|
47
|
-
// Automatically push metrics at intervals
|
|
46
|
+
// Automatically push metrics at intervals (staging: 60s; prod: 900 or 1800 for 15/30 min)
|
|
48
47
|
metricsClient.startPush(15) // interval in seconds
|
|
49
48
|
```
|
|
50
49
|
|
|
@@ -41,6 +41,7 @@ export class BaseMetricsClient {
|
|
|
41
41
|
intervalSec: number;
|
|
42
42
|
startupValidation: Function | undefined;
|
|
43
43
|
disablePushgateway: boolean;
|
|
44
|
+
removeOldMetrics: boolean;
|
|
44
45
|
prefixLogs: string;
|
|
45
46
|
_registry: client.Registry<"text/plain; version=0.0.4; charset=utf-8">;
|
|
46
47
|
defaultLabels: {
|
|
@@ -126,10 +127,15 @@ export class BaseMetricsClient {
|
|
|
126
127
|
*/
|
|
127
128
|
private _clearOldWorkers;
|
|
128
129
|
/**
|
|
129
|
-
*
|
|
130
|
+
* On shutdown: optionally delete this instance's metrics from VictoriaMetrics (by app, dyno_id, process_type).
|
|
130
131
|
* @returns {Promise<void>}
|
|
131
132
|
*/
|
|
132
133
|
gatewayDelete: () => Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Call VictoriaMetrics delete_series API to remove all series matching this instance's labels (app, dyno_id, process_type).
|
|
136
|
+
* @private
|
|
137
|
+
*/
|
|
138
|
+
private _deleteFromVMByLabels;
|
|
133
139
|
/**
|
|
134
140
|
* Push registry to configured URL (VM-agent). POST Prometheus text format + Basic auth.
|
|
135
141
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseMetricsClient.d.ts","sourceRoot":"","sources":["../../src/metrics/baseMetricsClient.js"],"names":[],"mappings":"AAKA;;;;GAIG;AACH;IACE;;;;;;;;;;;;;OAaG;IACH;QAZ2B,OAAO;QACP,MAAM;QACN,WAAW;QACV,OAAO;QACP,SAAS;QACV,cAAc;QACd,iBAAiB;QACjB,WAAW;QACV,gBAAgB;QACf,iBAAiB;QAClB,kBAAkB;
|
|
1
|
+
{"version":3,"file":"baseMetricsClient.d.ts","sourceRoot":"","sources":["../../src/metrics/baseMetricsClient.js"],"names":[],"mappings":"AAKA;;;;GAIG;AACH;IACE;;;;;;;;;;;;;OAaG;IACH;QAZ2B,OAAO;QACP,MAAM;QACN,WAAW;QACV,OAAO;QACP,SAAS;QACV,cAAc;QACd,iBAAiB;QACjB,WAAW;QACV,gBAAgB;QACf,iBAAiB;QAClB,kBAAkB;OAkD7C;IA/CC,gBAA4E;IAC5E,eAAqE;IACrE,oBAG6B;IAC7B,iBAAuE;IACvE,mBAC+D;IAC/D,uBACoE;IACpE,kBAC0E;IAC1E,oBAGI;IACJ,wCAAiD;IACjD,4BAEoD;IACpD,0BAEmD;IAEnD,mBAAyF;IAEzF,uEAAsC;IAGtC;;;;MAIC;IAGD,aAAmB;IACnB,WAAgB;IAChB,aAAkB;IAClB,sBAA2B;IAE3B,mEAAmE;IACnE;YADkB,MAAM,SAAc,MAAM,GAAG,QAAQ,MAAM,CAAC;MACvC;IAMzB;;;;;;;;OAQG;IACH;QAN2B,IAAI,EAApB,MAAM;QACU,IAAI,EAApB,MAAM;QACuC,QAAQ,UAAzC,MAAM,GAAC,QAAQ,MAAM,CAAC;QACf,UAAU;UAC3B,OAAO,aAAa,EAAE,KAAK,CAuBvC;IAED;;;;;;;;;;;OAWG;IACH;QAR0B,IAAI,EAAnB,MAAM;QACS,IAAI,EAAnB,MAAM;QACY,UAAU;kBAEhB,MAAM,mBAAmB,MAAM,KAAK,IAAI,CAuB9D;IAED;;OAEG;IACH,6BAKC;IAED;;OAEG;IACH,kCAiCC;IAED,sEA2CC;IAED,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;;;;MAEC;IAED,gCAGC;IAID,8BAEC;IAED,gCAEC;IAED,4EAEC;IAED,sCAEC;IAED,2DAWC;CACF"}
|
|
@@ -38,6 +38,7 @@ class BaseMetricsClient {
|
|
|
38
38
|
this.intervalSec = config.intervalSec || parseInt(process.env.METRICS_INTERVAL_SEC || '', 10) || 15;
|
|
39
39
|
this.startupValidation = config.startupValidation;
|
|
40
40
|
this.disablePushgateway = config.disablePushgateway ?? process.env.METRICS_DISABLE_PUSHGATEWAY === 'true';
|
|
41
|
+
this.removeOldMetrics = config.removeOldMetrics ?? process.env.METRICS_REMOVE_OLD_METRICS === 'true';
|
|
41
42
|
this.prefixLogs = `[${this.processType}] [${this.appName}] [${this.dynoId}] [Monitoring]`;
|
|
42
43
|
this._registry = new client.Registry();
|
|
43
44
|
client.collectDefaultMetrics({
|
|
@@ -249,11 +250,58 @@ class BaseMetricsClient {
|
|
|
249
250
|
};
|
|
250
251
|
|
|
251
252
|
/**
|
|
252
|
-
*
|
|
253
|
+
* On shutdown: optionally delete this instance's metrics from VictoriaMetrics (by app, dyno_id, process_type).
|
|
253
254
|
* @returns {Promise<void>}
|
|
254
255
|
*/
|
|
255
256
|
gatewayDelete = async () => {
|
|
256
|
-
|
|
257
|
+
if (this.removeOldMetrics && this.pushgatewayUrl && this.pushgatewayUrl.trim()) {
|
|
258
|
+
await this._deleteFromVMByLabels().catch(err => {
|
|
259
|
+
console.warn(`${this.prefixLogs} Deletion from VM on shutdown failed:`, err.message);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Call VictoriaMetrics delete_series API to remove all series matching this instance's labels (app, dyno_id, process_type).
|
|
266
|
+
* @private
|
|
267
|
+
*/
|
|
268
|
+
_deleteFromVMByLabels = () => {
|
|
269
|
+
const esc = s => String(s).replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
270
|
+
const selector = `{app="${esc(this.appName)}",dyno_id="${esc(this.dynoId)}",process_type="${esc(this.processType)}"}`;
|
|
271
|
+
let origin;
|
|
272
|
+
try {
|
|
273
|
+
const u = new URL((this.pushgatewayUrl || '').trim());
|
|
274
|
+
origin = u.origin;
|
|
275
|
+
} catch {
|
|
276
|
+
return Promise.reject(new Error('Invalid push URL'));
|
|
277
|
+
}
|
|
278
|
+
const path = `/api/v1/admin/tsdb/delete_series?match[]=${encodeURIComponent(selector)}`;
|
|
279
|
+
return new Promise((resolve, reject) => {
|
|
280
|
+
const u = new URL(origin);
|
|
281
|
+
const req = (u.protocol === 'https:' ? https : http).request({
|
|
282
|
+
hostname: u.hostname,
|
|
283
|
+
port: u.port || (u.protocol === 'https:' ? 443 : 80),
|
|
284
|
+
path,
|
|
285
|
+
method: 'POST',
|
|
286
|
+
headers: {
|
|
287
|
+
'Content-Length': '0',
|
|
288
|
+
Authorization: this.authToken ? `Basic ${this.authToken}` : undefined
|
|
289
|
+
},
|
|
290
|
+
agent: u.protocol === 'https:' ? new https.Agent({
|
|
291
|
+
keepAlive: false
|
|
292
|
+
}) : undefined
|
|
293
|
+
}, res => {
|
|
294
|
+
if (res.statusCode >= 200 && res.statusCode < 300) resolve();else {
|
|
295
|
+
let data = '';
|
|
296
|
+
res.on('data', chunk => {
|
|
297
|
+
data += chunk;
|
|
298
|
+
});
|
|
299
|
+
res.on('end', () => reject(new Error(`Delete failed: ${res.statusCode} ${data}`)));
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
req.on('error', reject);
|
|
303
|
+
req.end();
|
|
304
|
+
});
|
|
257
305
|
};
|
|
258
306
|
|
|
259
307
|
/**
|
|
@@ -304,7 +352,6 @@ class BaseMetricsClient {
|
|
|
304
352
|
}) : undefined
|
|
305
353
|
}, res => {
|
|
306
354
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
307
|
-
console.log(`${this.prefixLogs} Metrics pushed to ${u.origin} OK (${res.statusCode})`);
|
|
308
355
|
resolve();
|
|
309
356
|
} else {
|
|
310
357
|
let data = '';
|
|
@@ -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","enabled","METRICS_ENABLED","logValues","METRICS_LOG_VALUES","pushgatewayUrl","METRICS_PUSHGATEWAY_URL","authToken","pushgatewaySecret","METRICS_PUSHGATEWAY_SECRET","intervalSec","parseInt","METRICS_INTERVAL_SEC","startupValidation","disablePushgateway","METRICS_DISABLE_PUSHGATEWAY","prefixLogs","_registry","Registry","collectDefaultMetrics","register","defaultLabels","app","dyno_id","process_type","gateway","gauges","counters","countersFunctions","gaugeUpdaters","_clearOldWorkers","removeOldMetrics","_setCleanupHandlers","createGauge","name","help","updateFn","labelNames","Object","keys","g","Gauge","registers","createCounter","c","Counter","data","value","inc","clearAllCounters","metricsLogValues","console","log","values","forEach","counter","reset","_pushMetrics","entries","result","val","Promise","undefined","set","err","error","gatewayPush","metrics","getMetricsAsJSON","JSON","stringify","_startPush","interval","customPushMetics","warn","runPush","resolve","pushMetrics","setInterval","catch","pushOrigin","trim","origin","startPush","cleanup","gatewayDelete","exit","params","_pushToVMAgent","pushUrl","u","pathname","search","reject","req","protocol","request","hostname","port","path","method","headers","contentType","Authorization","agent","Agent","keepAlive","res","statusCode","on","chunk","Error","then","setHeader","Buffer","byteLength","end","withDefaultLabels","labels","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 */\n constructor(config = {}) {\n this.appName = config.appName || process.env.BUILD_APP_NAME || 'unknown-app'\n this.dynoId = config.dynoId || process.env.HOSTNAME || 'unknown-dyno'\n this.processType =\n config.processType ||\n process.env.BUILD_DYNO_PROCESS_TYPE ||\n 'undefined_build_dyno_type'\n this.enabled = config.enabled ?? process.env.METRICS_ENABLED === 'true'\n this.logValues =\n config.logValues ?? process.env.METRICS_LOG_VALUES === 'true'\n this.pushgatewayUrl =\n config.pushgatewayUrl || process.env.METRICS_PUSHGATEWAY_URL || ''\n this.authToken =\n config.pushgatewaySecret || process.env.METRICS_PUSHGATEWAY_SECRET || ''\n this.intervalSec =\n config.intervalSec ||\n parseInt(process.env.METRICS_INTERVAL_SEC || '', 10) ||\n 15\n this.startupValidation = config.startupValidation\n this.disablePushgateway =\n config.disablePushgateway ??\n process.env.METRICS_DISABLE_PUSHGATEWAY === 'true'\n\n this.prefixLogs = `[${this.processType}] [${this.appName}] [${this.dynoId}] [Monitoring]`\n\n this._registry = new client.Registry()\n client.collectDefaultMetrics({ register: this._registry })\n\n this.defaultLabels = {\n app: this.appName,\n dyno_id: this.dynoId,\n process_type: this.processType,\n }\n\n // 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\n /**\n * Create a gauge metric.\n * @param {Object} options - Gauge configuration\n * @param {string} options.name - Name of the gauge\n * @param {string} options.help - Help text describing the gauge\n * @param {function(): number|Promise<number>} [options.updateFn] - Optional function returning the gauge value\n * @param {string[]} [options.labelNames] - Optional custom label names\n * @returns {import('prom-client').Gauge} The created Prometheus gauge\n */\n createGauge = ({\n name,\n help,\n updateFn,\n labelNames = Object.keys(this.defaultLabels),\n }) => {\n if (this.gauges[name]) return this.gauges[name]\n\n const g = new client.Gauge({\n name,\n help,\n labelNames,\n registers: [this._registry],\n })\n this.gauges[name] = g\n\n if (updateFn && typeof updateFn === 'function') {\n this.gaugeUpdaters[name] = updateFn\n }\n\n return g\n }\n\n /**\n * Create a Prometheus Counter metric.\n *\n * @param {Object} params - Counter configuration\n * @param {string} params.name - Metric name\n * @param {string} params.help - Metric description\n * @param {string[]} [params.labelNames] - Optional list of label names. Defaults to this.defaultLabels keys.\n *\n * @returns {(labels?: Object, incrementValue?: number) => void}\n * A function to increment the counter.\n * Usage: (labels?, incrementValue?)\n */\n createCounter({ name, help, labelNames = Object.keys(this.defaultLabels) }) {\n if (this.counters[name]) return this.countersFunctions[name]\n\n const c = new client.Counter({\n name,\n help,\n labelNames,\n registers: [this._registry],\n })\n this.counters[name] = c\n\n this.countersFunctions = {\n ...this.countersFunctions,\n [name]: (data = {}, value = 1) => {\n c.inc({ ...this.defaultLabels, ...data }, value)\n },\n }\n\n return this.countersFunctions[name]\n }\n\n /**\n * Clear all collected counters\n */\n clearAllCounters = () => {\n if (this.metricsLogValues) {\n console.log('Counters to clear: ', Object.keys(this.counters))\n }\n Object.values(this.counters).forEach(counter => counter.reset())\n }\n\n /**\n * Push all gauges and counters to PushGateway and optionally log.\n */\n _pushMetrics = async () => {\n try {\n for (const [name, updateFn] of Object.entries(this.gaugeUpdaters)) {\n try {\n if (!updateFn) {\n continue\n }\n const result = updateFn()\n const val = result instanceof Promise ? await result : result\n if (val !== undefined) this.gauges[name].set(this.defaultLabels, val)\n } catch (err) {\n console.error(\n `${this.prefixLogs} Failed to update gauge ${name}:`,\n err\n )\n }\n }\n\n if (!this.disablePushgateway) {\n await this.gatewayPush()\n }\n // this.clearAllCounters() //TODO: or uncommit or delete (based on grafana expectation)\n\n if (this.logValues) {\n const metrics = await this._registry.getMetricsAsJSON()\n console.log(\n `${this.prefixLogs} Metrics:\\n`,\n JSON.stringify(metrics, null, 2)\n )\n }\n } catch (err) {\n console.error(`${this.prefixLogs} Failed to push metrics:`, err)\n }\n }\n\n _startPush = (interval = this.intervalSec, customPushMetics = undefined) => {\n if (!this.enabled) {\n console.warn(`${this.prefixLogs} Metrics disabled`)\n return\n }\n\n if (this.startupValidation && !this.startupValidation()) {\n return\n }\n\n 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 * No-op (no Pushgateway). Kept for API compatibility.\n * @returns {Promise<void>}\n */\n gatewayDelete = async () => {\n return Promise.resolve()\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 console.log(\n `${this.prefixLogs} Metrics pushed to ${u.origin} OK (${res.statusCode})`\n )\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 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","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","gateway","gauges","counters","countersFunctions","gaugeUpdaters","_clearOldWorkers","_setCleanupHandlers","createGauge","name","help","updateFn","labelNames","Object","keys","g","Gauge","registers","createCounter","c","Counter","data","value","inc","clearAllCounters","metricsLogValues","console","log","values","forEach","counter","reset","_pushMetrics","entries","result","val","Promise","undefined","set","err","error","gatewayPush","metrics","getMetricsAsJSON","JSON","stringify","_startPush","interval","customPushMetics","warn","runPush","resolve","pushMetrics","setInterval","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","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 */\n constructor(config = {}) {\n this.appName = config.appName || process.env.BUILD_APP_NAME || 'unknown-app'\n this.dynoId = config.dynoId || process.env.HOSTNAME || 'unknown-dyno'\n this.processType =\n config.processType ||\n process.env.BUILD_DYNO_PROCESS_TYPE ||\n 'undefined_build_dyno_type'\n this.enabled = config.enabled ?? process.env.METRICS_ENABLED === 'true'\n this.logValues =\n config.logValues ?? process.env.METRICS_LOG_VALUES === 'true'\n this.pushgatewayUrl =\n config.pushgatewayUrl || process.env.METRICS_PUSHGATEWAY_URL || ''\n this.authToken =\n config.pushgatewaySecret || process.env.METRICS_PUSHGATEWAY_SECRET || ''\n this.intervalSec =\n config.intervalSec ||\n parseInt(process.env.METRICS_INTERVAL_SEC || '', 10) ||\n 15\n this.startupValidation = config.startupValidation\n this.disablePushgateway =\n config.disablePushgateway ??\n process.env.METRICS_DISABLE_PUSHGATEWAY === 'true'\n 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 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 // 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\n /**\n * Create a gauge metric.\n * @param {Object} options - Gauge configuration\n * @param {string} options.name - Name of the gauge\n * @param {string} options.help - Help text describing the gauge\n * @param {function(): number|Promise<number>} [options.updateFn] - Optional function returning the gauge value\n * @param {string[]} [options.labelNames] - Optional custom label names\n * @returns {import('prom-client').Gauge} The created Prometheus gauge\n */\n createGauge = ({\n name,\n help,\n updateFn,\n labelNames = Object.keys(this.defaultLabels),\n }) => {\n if (this.gauges[name]) return this.gauges[name]\n\n const g = new client.Gauge({\n name,\n help,\n labelNames,\n registers: [this._registry],\n })\n this.gauges[name] = g\n\n if (updateFn && typeof updateFn === 'function') {\n this.gaugeUpdaters[name] = updateFn\n }\n\n return g\n }\n\n /**\n * Create a Prometheus Counter metric.\n *\n * @param {Object} params - Counter configuration\n * @param {string} params.name - Metric name\n * @param {string} params.help - Metric description\n * @param {string[]} [params.labelNames] - Optional list of label names. Defaults to this.defaultLabels keys.\n *\n * @returns {(labels?: Object, incrementValue?: number) => void}\n * A function to increment the counter.\n * Usage: (labels?, incrementValue?)\n */\n createCounter({ name, help, labelNames = Object.keys(this.defaultLabels) }) {\n if (this.counters[name]) return this.countersFunctions[name]\n\n const c = new client.Counter({\n name,\n help,\n labelNames,\n registers: [this._registry],\n })\n this.counters[name] = c\n\n this.countersFunctions = {\n ...this.countersFunctions,\n [name]: (data = {}, value = 1) => {\n c.inc({ ...this.defaultLabels, ...data }, value)\n },\n }\n\n return this.countersFunctions[name]\n }\n\n /**\n * Clear all collected counters\n */\n clearAllCounters = () => {\n if (this.metricsLogValues) {\n console.log('Counters to clear: ', Object.keys(this.counters))\n }\n Object.values(this.counters).forEach(counter => counter.reset())\n }\n\n /**\n * Push all gauges and counters to PushGateway and optionally log.\n */\n _pushMetrics = async () => {\n try {\n for (const [name, updateFn] of Object.entries(this.gaugeUpdaters)) {\n try {\n if (!updateFn) {\n continue\n }\n const result = updateFn()\n const val = result instanceof Promise ? await result : result\n if (val !== undefined) this.gauges[name].set(this.defaultLabels, val)\n } catch (err) {\n console.error(\n `${this.prefixLogs} Failed to update gauge ${name}:`,\n err\n )\n }\n }\n\n if (!this.disablePushgateway) {\n await this.gatewayPush()\n }\n // this.clearAllCounters() //TODO: or uncommit or delete (based on grafana expectation)\n\n if (this.logValues) {\n const metrics = await this._registry.getMetricsAsJSON()\n console.log(\n `${this.prefixLogs} Metrics:\\n`,\n JSON.stringify(metrics, null, 2)\n )\n }\n } catch (err) {\n console.error(`${this.prefixLogs} Failed to push metrics:`, err)\n }\n }\n\n _startPush = (interval = this.intervalSec, customPushMetics = undefined) => {\n if (!this.enabled) {\n console.warn(`${this.prefixLogs} Metrics disabled`)\n return\n }\n\n if (this.startupValidation && !this.startupValidation()) {\n return\n }\n\n 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 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":[]}
|
package/package.json
CHANGED
|
@@ -45,6 +45,9 @@ class BaseMetricsClient {
|
|
|
45
45
|
this.disablePushgateway =
|
|
46
46
|
config.disablePushgateway ??
|
|
47
47
|
process.env.METRICS_DISABLE_PUSHGATEWAY === 'true'
|
|
48
|
+
this.removeOldMetrics =
|
|
49
|
+
config.removeOldMetrics ??
|
|
50
|
+
process.env.METRICS_REMOVE_OLD_METRICS === 'true'
|
|
48
51
|
|
|
49
52
|
this.prefixLogs = `[${this.processType}] [${this.appName}] [${this.dynoId}] [Monitoring]`
|
|
50
53
|
|
|
@@ -272,11 +275,78 @@ class BaseMetricsClient {
|
|
|
272
275
|
}
|
|
273
276
|
|
|
274
277
|
/**
|
|
275
|
-
*
|
|
278
|
+
* On shutdown: optionally delete this instance's metrics from VictoriaMetrics (by app, dyno_id, process_type).
|
|
276
279
|
* @returns {Promise<void>}
|
|
277
280
|
*/
|
|
278
281
|
gatewayDelete = async () => {
|
|
279
|
-
|
|
282
|
+
if (
|
|
283
|
+
this.removeOldMetrics &&
|
|
284
|
+
this.pushgatewayUrl &&
|
|
285
|
+
this.pushgatewayUrl.trim()
|
|
286
|
+
) {
|
|
287
|
+
await this._deleteFromVMByLabels().catch(err => {
|
|
288
|
+
console.warn(
|
|
289
|
+
`${this.prefixLogs} Deletion from VM on shutdown failed:`,
|
|
290
|
+
err.message
|
|
291
|
+
)
|
|
292
|
+
})
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Call VictoriaMetrics delete_series API to remove all series matching this instance's labels (app, dyno_id, process_type).
|
|
298
|
+
* @private
|
|
299
|
+
*/
|
|
300
|
+
_deleteFromVMByLabels = () => {
|
|
301
|
+
const esc = s => String(s).replace(/\\/g, '\\\\').replace(/"/g, '\\"')
|
|
302
|
+
const selector = `{app="${esc(this.appName)}",dyno_id="${esc(
|
|
303
|
+
this.dynoId
|
|
304
|
+
)}",process_type="${esc(this.processType)}"}`
|
|
305
|
+
let origin
|
|
306
|
+
try {
|
|
307
|
+
const u = new URL((this.pushgatewayUrl || '').trim())
|
|
308
|
+
origin = u.origin
|
|
309
|
+
} catch {
|
|
310
|
+
return Promise.reject(new Error('Invalid push URL'))
|
|
311
|
+
}
|
|
312
|
+
const path = `/api/v1/admin/tsdb/delete_series?match[]=${encodeURIComponent(
|
|
313
|
+
selector
|
|
314
|
+
)}`
|
|
315
|
+
return new Promise((resolve, reject) => {
|
|
316
|
+
const u = new URL(origin)
|
|
317
|
+
const req = (u.protocol === 'https:' ? https : http).request(
|
|
318
|
+
{
|
|
319
|
+
hostname: u.hostname,
|
|
320
|
+
port: u.port || (u.protocol === 'https:' ? 443 : 80),
|
|
321
|
+
path,
|
|
322
|
+
method: 'POST',
|
|
323
|
+
headers: {
|
|
324
|
+
'Content-Length': '0',
|
|
325
|
+
Authorization: this.authToken
|
|
326
|
+
? `Basic ${this.authToken}`
|
|
327
|
+
: undefined,
|
|
328
|
+
},
|
|
329
|
+
agent:
|
|
330
|
+
u.protocol === 'https:'
|
|
331
|
+
? new https.Agent({ keepAlive: false })
|
|
332
|
+
: undefined,
|
|
333
|
+
},
|
|
334
|
+
res => {
|
|
335
|
+
if (res.statusCode >= 200 && res.statusCode < 300) resolve()
|
|
336
|
+
else {
|
|
337
|
+
let data = ''
|
|
338
|
+
res.on('data', chunk => {
|
|
339
|
+
data += chunk
|
|
340
|
+
})
|
|
341
|
+
res.on('end', () =>
|
|
342
|
+
reject(new Error(`Delete failed: ${res.statusCode} ${data}`))
|
|
343
|
+
)
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
)
|
|
347
|
+
req.on('error', reject)
|
|
348
|
+
req.end()
|
|
349
|
+
})
|
|
280
350
|
}
|
|
281
351
|
|
|
282
352
|
/**
|
|
@@ -336,9 +406,6 @@ class BaseMetricsClient {
|
|
|
336
406
|
},
|
|
337
407
|
res => {
|
|
338
408
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
339
|
-
console.log(
|
|
340
|
-
`${this.prefixLogs} Metrics pushed to ${u.origin} OK (${res.statusCode})`
|
|
341
|
-
)
|
|
342
409
|
resolve()
|
|
343
410
|
} else {
|
|
344
411
|
let data = ''
|