@tramvai/module-metrics 1.58.1 → 1.61.0

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
@@ -162,4 +162,4 @@ The module uses loggers with the next ids: `metrics:perf`, `metrics:papi`
162
162
 
163
163
  ## Exported tokens
164
164
 
165
- [link](references/tokens/metrics-tokens.md)
165
+ [link](references/tokens/metrics.md)
@@ -1,11 +1,3 @@
1
- declare type Args = [Record<string, any> | string | URL, (res: Record<string, any>) => void] | [string | URL, Record<string, any>, (res: Record<string, any>) => void];
1
+ import type { Args, CreateRequestWithMetrics } from './types';
2
2
  export declare const getUrlAndOptions: (args: Args) => any[];
3
- export declare const createRequestWithMetrics: ({ metricsInstances: { requestsTotal, requestsErrors, requestsDuration }, getServiceName, }: {
4
- metricsInstances: {
5
- requestsTotal: any;
6
- requestsErrors: any;
7
- requestsDuration: any;
8
- };
9
- getServiceName: any;
10
- }) => (originalRequest: any, ...args: Args) => any;
11
- export {};
3
+ export declare const createRequestWithMetrics: CreateRequestWithMetrics;
@@ -1,7 +1,9 @@
1
- export declare const initRequestsMetrics: ({ metrics, getServiceName, http, https, createRequestWithMetrics, }: {
2
- metrics: any;
3
- getServiceName: any;
4
- http: any;
5
- https: any;
6
- createRequestWithMetrics: any;
1
+ import type { MetricsModule, GetServiceName, CreateRequestWithMetrics, HttpModule, HttpsModule, ModuleConfig } from './types';
2
+ export declare const initRequestsMetrics: ({ metrics, getServiceName, http, https, createRequestWithMetrics, config, }: {
3
+ metrics: MetricsModule;
4
+ http: HttpModule;
5
+ https: HttpsModule;
6
+ createRequestWithMetrics: CreateRequestWithMetrics;
7
+ getServiceName: GetServiceName;
8
+ config: ModuleConfig;
7
9
  }) => void;
@@ -0,0 +1,26 @@
1
+ /// <reference types="node" />
2
+ import type { RequestOptions, IncomingMessage, ClientRequest } from 'http';
3
+ import type httpType from 'http';
4
+ import type httpsType from 'https';
5
+ import type { Counter, Histogram } from 'prom-client';
6
+ import type { METRICS_MODULE_TOKEN, METRICS_SERVICES_REGISTRY_TOKEN } from '@tramvai/tokens-metrics';
7
+ export declare type ModuleConfig = {
8
+ enableDnsResolveMetric: boolean;
9
+ };
10
+ export declare type MetricsModule = typeof METRICS_MODULE_TOKEN;
11
+ export declare type HttpModule = typeof httpType;
12
+ export declare type HttpsModule = typeof httpsType;
13
+ export declare type OriginalRequest = HttpModule['request'];
14
+ export declare type MetricsInstances = {
15
+ requestsTotal: Counter<'status' | 'method' | 'service'>;
16
+ requestsErrors: Counter<'status' | 'method' | 'service'>;
17
+ requestsDuration: Histogram<'status' | 'method' | 'service'>;
18
+ dnsResolveDuration: Histogram<'service'>;
19
+ };
20
+ export declare type GetServiceName = typeof METRICS_SERVICES_REGISTRY_TOKEN['getServiceName'];
21
+ export declare type Args = [RequestOptions | string | URL, (res: IncomingMessage) => void] | [string | URL, RequestOptions, (res: IncomingMessage) => void];
22
+ export declare type CreateRequestWithMetrics = (args: {
23
+ metricsInstances: MetricsInstances;
24
+ getServiceName: GetServiceName;
25
+ config: ModuleConfig;
26
+ }) => (originalRequest: HttpModule['request'], ...requestArgs: Args) => ClientRequest;
package/lib/server.d.ts CHANGED
@@ -1,2 +1,4 @@
1
+ import { METRICS_MODULE_CONFIG_TOKEN } from './tokens';
1
2
  export declare class MetricsModule {
2
3
  }
4
+ export { METRICS_MODULE_CONFIG_TOKEN };
package/lib/server.es.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { __decorate } from 'tslib';
2
- import { Module, commandLineListTokens, Scope } from '@tramvai/core';
2
+ import { createToken, Module, commandLineListTokens, Scope, provide } from '@tramvai/core';
3
3
  import { SERVER_MODULE_PAPI_PUBLIC_ROUTE, WEB_APP_BEFORE_INIT_TOKEN, WEB_APP_TOKEN, SPECIAL_SERVER_PATHS } from '@tramvai/tokens-server';
4
4
  import { METRICS_MODULE_TOKEN, METRICS_SERVICES_REGISTRY_TOKEN, REGISTER_INSTANT_METRIC_TOKEN } from '@tramvai/tokens-metrics';
5
5
  import { measure } from '@tinkoff/measure-express-requests';
@@ -16,6 +16,15 @@ import { createPapiMethod } from '@tramvai/papi';
16
16
  import fromPairs from '@tinkoff/utils/object/fromPairs';
17
17
  import { createEvent, createReducer } from '@tramvai/state';
18
18
 
19
+ // https://nodejs.org/api/errors.html#nodejs-error-codes - Common system errors possible for net/http/dns
20
+ const POSSIBLE_ERRORS = [
21
+ 'EADDRINUSE',
22
+ 'ECONNREFUSED',
23
+ 'ECONNRESET',
24
+ 'ENOTFOUND',
25
+ 'EPIPE',
26
+ 'ETIMEDOUT',
27
+ ];
19
28
  const getUrlAndOptions = (args) => {
20
29
  let url;
21
30
  let options;
@@ -59,33 +68,44 @@ const getUrlAndOptions = (args) => {
59
68
  const urlWOQuery = parsedUrl.origin + parsedUrl.pathname;
60
69
  return [urlWOQuery, options || {}];
61
70
  };
62
- const createRequestWithMetrics = ({ metricsInstances: { requestsTotal, requestsErrors, requestsDuration }, getServiceName, }) => function requestWithMetrics(originalRequest, ...args) {
63
- const req = originalRequest.apply(this, args);
64
- const timerDone = requestsDuration.startTimer();
71
+ const createRequestWithMetrics = ({ metricsInstances: { requestsTotal, requestsErrors, requestsDuration, dnsResolveDuration }, getServiceName, config, }) => function requestWithMetrics(originalRequest, ...args) {
65
72
  const [url, options] = getUrlAndOptions(args);
66
73
  const serviceName = getServiceName(url);
74
+ const req = originalRequest.apply(this, args);
75
+ const timerDone = requestsDuration.startTimer();
67
76
  const labelsValues = {
68
77
  method: options.method || 'unknown',
69
78
  service: serviceName || new URL(url).origin || 'unknown',
70
79
  status: 'unknown',
71
80
  };
72
81
  req.on('response', (res) => {
73
- labelsValues.status = res.statusCode;
82
+ labelsValues.status = res.statusCode.toString();
74
83
  if (res.statusCode >= 400) {
75
84
  requestsErrors.inc(labelsValues);
76
85
  }
77
86
  requestsTotal.inc(labelsValues);
78
87
  timerDone(labelsValues);
79
88
  });
80
- req.on('error', () => {
89
+ req.on('error', (e) => {
90
+ if (POSSIBLE_ERRORS.includes(e === null || e === void 0 ? void 0 : e.code)) {
91
+ labelsValues.status = e.code;
92
+ }
81
93
  requestsTotal.inc(labelsValues);
82
94
  requestsErrors.inc(labelsValues);
83
95
  timerDone(labelsValues);
84
96
  });
97
+ if (config.enableDnsResolveMetric) {
98
+ req.on('socket', (socket) => {
99
+ const dnsTimerDone = dnsResolveDuration.startTimer();
100
+ socket.on('lookup', () => {
101
+ dnsTimerDone({ service: labelsValues.service });
102
+ });
103
+ });
104
+ }
85
105
  return req;
86
106
  };
87
107
 
88
- const initRequestsMetrics = ({ metrics, getServiceName, http, https, createRequestWithMetrics, }) => {
108
+ const initRequestsMetrics = ({ metrics, getServiceName, http, https, createRequestWithMetrics, config, }) => {
89
109
  const metricsInstances = {
90
110
  requestsTotal: metrics.counter({
91
111
  name: 'http_sent_requests_total',
@@ -102,16 +122,21 @@ const initRequestsMetrics = ({ metrics, getServiceName, http, https, createReque
102
122
  help: 'Execution time of the sent requests',
103
123
  labelNames: ['status', 'method', 'service'],
104
124
  }),
125
+ dnsResolveDuration: metrics.histogram({
126
+ name: 'dns_resolve_duration',
127
+ help: 'Time for dns resolve of the outhgoing requests',
128
+ labelNames: ['service'],
129
+ }),
105
130
  };
106
131
  monkeypatch({
107
132
  obj: https,
108
133
  method: 'request',
109
- handler: createRequestWithMetrics({ metricsInstances, getServiceName }),
134
+ handler: createRequestWithMetrics({ metricsInstances, getServiceName, config }),
110
135
  });
111
136
  monkeypatch({
112
137
  obj: http,
113
138
  method: 'request',
114
- handler: createRequestWithMetrics({ metricsInstances, getServiceName }),
139
+ handler: createRequestWithMetrics({ metricsInstances, getServiceName, config }),
115
140
  });
116
141
  };
117
142
 
@@ -214,6 +239,8 @@ class MetricsServicesRegistry {
214
239
  }
215
240
  }
216
241
 
242
+ const METRICS_MODULE_CONFIG_TOKEN = createToken('metrics-module-config');
243
+
217
244
  let RequestModule = class RequestModule {
218
245
  };
219
246
  RequestModule = __decorate([
@@ -222,7 +249,7 @@ RequestModule = __decorate([
222
249
  {
223
250
  provide: commandLineListTokens.init,
224
251
  multi: true,
225
- useFactory: ({ metrics, envManager, metricsServicesRegistry }) => {
252
+ useFactory: ({ metrics, envManager, metricsServicesRegistry, metricsModuleConfig, }) => {
226
253
  if (!metrics) {
227
254
  return noop;
228
255
  }
@@ -230,7 +257,14 @@ RequestModule = __decorate([
230
257
  const env = envManager.getAll();
231
258
  metricsServicesRegistry.registerEnv(env);
232
259
  const getServiceName = metricsServicesRegistry.getServiceName.bind(metricsServicesRegistry);
233
- initRequestsMetrics({ metrics, getServiceName, http, https, createRequestWithMetrics });
260
+ initRequestsMetrics({
261
+ metrics,
262
+ getServiceName,
263
+ http,
264
+ https,
265
+ createRequestWithMetrics,
266
+ config: metricsModuleConfig,
267
+ });
234
268
  };
235
269
  },
236
270
  deps: {
@@ -240,6 +274,7 @@ RequestModule = __decorate([
240
274
  },
241
275
  metricsServicesRegistry: METRICS_SERVICES_REGISTRY_TOKEN,
242
276
  envManager: ENV_MANAGER_TOKEN,
277
+ metricsModuleConfig: METRICS_MODULE_CONFIG_TOKEN,
243
278
  },
244
279
  },
245
280
  {
@@ -378,11 +413,17 @@ MetricsModule = __decorate([
378
413
  Module({
379
414
  imports: [RequestModule, InstantMetricsModule],
380
415
  providers: [
381
- {
416
+ provide({
417
+ provide: METRICS_MODULE_CONFIG_TOKEN,
418
+ useValue: {
419
+ enableDnsResolveMetric: false,
420
+ },
421
+ }),
422
+ provide({
382
423
  provide: 'metricsDefaultRegistry',
383
424
  useClass: Registry,
384
- },
385
- {
425
+ }),
426
+ provide({
386
427
  provide: METRICS_MODULE_TOKEN,
387
428
  useFactory: ({ registry }) => {
388
429
  collectDefaultMetrics({ register: registry });
@@ -397,8 +438,8 @@ MetricsModule = __decorate([
397
438
  deps: {
398
439
  registry: 'metricsDefaultRegistry',
399
440
  },
400
- },
401
- {
441
+ }),
442
+ provide({
402
443
  provide: WEB_APP_BEFORE_INIT_TOKEN,
403
444
  useFactory: ({ metrics, app, additionalLabelNamesList, getAdditionalLabelValuesList, httpRequestsDurationBuckets, metricsExcludePaths, registry, }) => {
404
445
  return () => {
@@ -444,8 +485,8 @@ MetricsModule = __decorate([
444
485
  registry: 'metricsDefaultRegistry',
445
486
  },
446
487
  multi: true,
447
- },
448
- {
488
+ }),
489
+ provide({
449
490
  provide: WEB_APP_BEFORE_INIT_TOKEN,
450
491
  useFactory: ({ metrics }) => {
451
492
  return () => {
@@ -456,9 +497,9 @@ MetricsModule = __decorate([
456
497
  metrics: METRICS_MODULE_TOKEN,
457
498
  },
458
499
  multi: true,
459
- },
500
+ }),
460
501
  ],
461
502
  })
462
503
  ], MetricsModule);
463
504
 
464
- export { MetricsModule };
505
+ export { METRICS_MODULE_CONFIG_TOKEN, MetricsModule };
package/lib/server.js CHANGED
@@ -30,6 +30,15 @@ var monkeypatch__default = /*#__PURE__*/_interopDefaultLegacy(monkeypatch);
30
30
  var isString__default = /*#__PURE__*/_interopDefaultLegacy(isString);
31
31
  var fromPairs__default = /*#__PURE__*/_interopDefaultLegacy(fromPairs);
32
32
 
33
+ // https://nodejs.org/api/errors.html#nodejs-error-codes - Common system errors possible for net/http/dns
34
+ const POSSIBLE_ERRORS = [
35
+ 'EADDRINUSE',
36
+ 'ECONNREFUSED',
37
+ 'ECONNRESET',
38
+ 'ENOTFOUND',
39
+ 'EPIPE',
40
+ 'ETIMEDOUT',
41
+ ];
33
42
  const getUrlAndOptions = (args) => {
34
43
  let url$1;
35
44
  let options;
@@ -73,33 +82,44 @@ const getUrlAndOptions = (args) => {
73
82
  const urlWOQuery = parsedUrl.origin + parsedUrl.pathname;
74
83
  return [urlWOQuery, options || {}];
75
84
  };
76
- const createRequestWithMetrics = ({ metricsInstances: { requestsTotal, requestsErrors, requestsDuration }, getServiceName, }) => function requestWithMetrics(originalRequest, ...args) {
77
- const req = originalRequest.apply(this, args);
78
- const timerDone = requestsDuration.startTimer();
85
+ const createRequestWithMetrics = ({ metricsInstances: { requestsTotal, requestsErrors, requestsDuration, dnsResolveDuration }, getServiceName, config, }) => function requestWithMetrics(originalRequest, ...args) {
79
86
  const [url, options] = getUrlAndOptions(args);
80
87
  const serviceName = getServiceName(url);
88
+ const req = originalRequest.apply(this, args);
89
+ const timerDone = requestsDuration.startTimer();
81
90
  const labelsValues = {
82
91
  method: options.method || 'unknown',
83
92
  service: serviceName || new URL(url).origin || 'unknown',
84
93
  status: 'unknown',
85
94
  };
86
95
  req.on('response', (res) => {
87
- labelsValues.status = res.statusCode;
96
+ labelsValues.status = res.statusCode.toString();
88
97
  if (res.statusCode >= 400) {
89
98
  requestsErrors.inc(labelsValues);
90
99
  }
91
100
  requestsTotal.inc(labelsValues);
92
101
  timerDone(labelsValues);
93
102
  });
94
- req.on('error', () => {
103
+ req.on('error', (e) => {
104
+ if (POSSIBLE_ERRORS.includes(e === null || e === void 0 ? void 0 : e.code)) {
105
+ labelsValues.status = e.code;
106
+ }
95
107
  requestsTotal.inc(labelsValues);
96
108
  requestsErrors.inc(labelsValues);
97
109
  timerDone(labelsValues);
98
110
  });
111
+ if (config.enableDnsResolveMetric) {
112
+ req.on('socket', (socket) => {
113
+ const dnsTimerDone = dnsResolveDuration.startTimer();
114
+ socket.on('lookup', () => {
115
+ dnsTimerDone({ service: labelsValues.service });
116
+ });
117
+ });
118
+ }
99
119
  return req;
100
120
  };
101
121
 
102
- const initRequestsMetrics = ({ metrics, getServiceName, http, https, createRequestWithMetrics, }) => {
122
+ const initRequestsMetrics = ({ metrics, getServiceName, http, https, createRequestWithMetrics, config, }) => {
103
123
  const metricsInstances = {
104
124
  requestsTotal: metrics.counter({
105
125
  name: 'http_sent_requests_total',
@@ -116,16 +136,21 @@ const initRequestsMetrics = ({ metrics, getServiceName, http, https, createReque
116
136
  help: 'Execution time of the sent requests',
117
137
  labelNames: ['status', 'method', 'service'],
118
138
  }),
139
+ dnsResolveDuration: metrics.histogram({
140
+ name: 'dns_resolve_duration',
141
+ help: 'Time for dns resolve of the outhgoing requests',
142
+ labelNames: ['service'],
143
+ }),
119
144
  };
120
145
  monkeypatch__default["default"]({
121
146
  obj: https,
122
147
  method: 'request',
123
- handler: createRequestWithMetrics({ metricsInstances, getServiceName }),
148
+ handler: createRequestWithMetrics({ metricsInstances, getServiceName, config }),
124
149
  });
125
150
  monkeypatch__default["default"]({
126
151
  obj: http,
127
152
  method: 'request',
128
- handler: createRequestWithMetrics({ metricsInstances, getServiceName }),
153
+ handler: createRequestWithMetrics({ metricsInstances, getServiceName, config }),
129
154
  });
130
155
  };
131
156
 
@@ -228,6 +253,8 @@ class MetricsServicesRegistry {
228
253
  }
229
254
  }
230
255
 
256
+ const METRICS_MODULE_CONFIG_TOKEN = core.createToken('metrics-module-config');
257
+
231
258
  let RequestModule = class RequestModule {
232
259
  };
233
260
  RequestModule = tslib.__decorate([
@@ -236,7 +263,7 @@ RequestModule = tslib.__decorate([
236
263
  {
237
264
  provide: core.commandLineListTokens.init,
238
265
  multi: true,
239
- useFactory: ({ metrics, envManager, metricsServicesRegistry }) => {
266
+ useFactory: ({ metrics, envManager, metricsServicesRegistry, metricsModuleConfig, }) => {
240
267
  if (!metrics) {
241
268
  return noop__default["default"];
242
269
  }
@@ -244,7 +271,14 @@ RequestModule = tslib.__decorate([
244
271
  const env = envManager.getAll();
245
272
  metricsServicesRegistry.registerEnv(env);
246
273
  const getServiceName = metricsServicesRegistry.getServiceName.bind(metricsServicesRegistry);
247
- initRequestsMetrics({ metrics, getServiceName, http: http__default["default"], https: https__default["default"], createRequestWithMetrics });
274
+ initRequestsMetrics({
275
+ metrics,
276
+ getServiceName,
277
+ http: http__default["default"],
278
+ https: https__default["default"],
279
+ createRequestWithMetrics,
280
+ config: metricsModuleConfig,
281
+ });
248
282
  };
249
283
  },
250
284
  deps: {
@@ -254,6 +288,7 @@ RequestModule = tslib.__decorate([
254
288
  },
255
289
  metricsServicesRegistry: tokensMetrics.METRICS_SERVICES_REGISTRY_TOKEN,
256
290
  envManager: moduleCommon.ENV_MANAGER_TOKEN,
291
+ metricsModuleConfig: METRICS_MODULE_CONFIG_TOKEN,
257
292
  },
258
293
  },
259
294
  {
@@ -392,11 +427,17 @@ exports.MetricsModule = tslib.__decorate([
392
427
  core.Module({
393
428
  imports: [RequestModule, InstantMetricsModule],
394
429
  providers: [
395
- {
430
+ core.provide({
431
+ provide: METRICS_MODULE_CONFIG_TOKEN,
432
+ useValue: {
433
+ enableDnsResolveMetric: false,
434
+ },
435
+ }),
436
+ core.provide({
396
437
  provide: 'metricsDefaultRegistry',
397
438
  useClass: promClient.Registry,
398
- },
399
- {
439
+ }),
440
+ core.provide({
400
441
  provide: tokensMetrics.METRICS_MODULE_TOKEN,
401
442
  useFactory: ({ registry }) => {
402
443
  promClient.collectDefaultMetrics({ register: registry });
@@ -411,8 +452,8 @@ exports.MetricsModule = tslib.__decorate([
411
452
  deps: {
412
453
  registry: 'metricsDefaultRegistry',
413
454
  },
414
- },
415
- {
455
+ }),
456
+ core.provide({
416
457
  provide: tokensServer.WEB_APP_BEFORE_INIT_TOKEN,
417
458
  useFactory: ({ metrics, app, additionalLabelNamesList, getAdditionalLabelValuesList, httpRequestsDurationBuckets, metricsExcludePaths, registry, }) => {
418
459
  return () => {
@@ -458,8 +499,8 @@ exports.MetricsModule = tslib.__decorate([
458
499
  registry: 'metricsDefaultRegistry',
459
500
  },
460
501
  multi: true,
461
- },
462
- {
502
+ }),
503
+ core.provide({
463
504
  provide: tokensServer.WEB_APP_BEFORE_INIT_TOKEN,
464
505
  useFactory: ({ metrics }) => {
465
506
  return () => {
@@ -470,7 +511,9 @@ exports.MetricsModule = tslib.__decorate([
470
511
  metrics: tokensMetrics.METRICS_MODULE_TOKEN,
471
512
  },
472
513
  multi: true,
473
- },
514
+ }),
474
515
  ],
475
516
  })
476
517
  ], exports.MetricsModule);
518
+
519
+ exports.METRICS_MODULE_CONFIG_TOKEN = METRICS_MODULE_CONFIG_TOKEN;
@@ -0,0 +1,2 @@
1
+ import type { ModuleConfig } from './request/types';
2
+ export declare const METRICS_MODULE_CONFIG_TOKEN: ModuleConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tramvai/module-metrics",
3
- "version": "1.58.1",
3
+ "version": "1.61.0",
4
4
  "description": "",
5
5
  "browser": "lib/browser.js",
6
6
  "main": "lib/server.js",
@@ -19,13 +19,13 @@
19
19
  "build-for-publish": "true"
20
20
  },
21
21
  "dependencies": {
22
- "@tramvai/core": "1.58.1",
23
- "@tramvai/tokens-server": "1.58.1",
24
- "@tramvai/tokens-metrics": "1.58.1",
25
- "@tramvai/module-common": "1.58.1",
26
- "@tramvai/tokens-http-client": "1.58.1",
27
- "@tramvai/state": "1.58.1",
28
- "@tramvai/papi": "1.58.1",
22
+ "@tramvai/core": "1.61.0",
23
+ "@tramvai/tokens-server": "1.61.0",
24
+ "@tramvai/tokens-metrics": "1.61.0",
25
+ "@tramvai/module-common": "1.61.0",
26
+ "@tramvai/tokens-http-client": "1.61.0",
27
+ "@tramvai/state": "1.61.0",
28
+ "@tramvai/papi": "1.61.0",
29
29
  "@tinkoff/measure-express-requests": "1.4.2",
30
30
  "@tinkoff/monkeypatch": "1.3.3",
31
31
  "@tinkoff/url": "0.7.37",