@tramvai/module-metrics 2.70.1 → 2.72.3

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.
Files changed (33) hide show
  1. package/lib/browser.js +5 -156
  2. package/lib/constants.es.js +3 -0
  3. package/lib/constants.js +7 -0
  4. package/lib/instantMetrics/browser.browser.js +70 -0
  5. package/lib/instantMetrics/server.es.js +97 -0
  6. package/lib/instantMetrics/server.js +103 -0
  7. package/lib/instantMetrics/shared.browser.js +12 -0
  8. package/lib/instantMetrics/shared.es.js +12 -0
  9. package/lib/instantMetrics/shared.js +16 -0
  10. package/lib/instantMetrics/store.browser.js +8 -0
  11. package/lib/instantMetrics/store.es.js +8 -0
  12. package/lib/instantMetrics/store.js +13 -0
  13. package/lib/metrics/commandLine.es.js +22 -0
  14. package/lib/metrics/commandLine.js +26 -0
  15. package/lib/metrics/eventLoop.es.js +23 -0
  16. package/lib/metrics/eventLoop.js +27 -0
  17. package/lib/performance-devtools/PerfMetrics.browser.js +56 -0
  18. package/lib/performance-devtools/startMeasure.browser.js +14 -0
  19. package/lib/performance-devtools/supportsUserTiming.browser.js +7 -0
  20. package/lib/performance-devtools/uniqueId.browser.js +7 -0
  21. package/lib/request/MetricsServicesRegistry.es.js +56 -0
  22. package/lib/request/MetricsServicesRegistry.js +64 -0
  23. package/lib/request/PrefixTree.es.js +48 -0
  24. package/lib/request/PrefixTree.js +52 -0
  25. package/lib/request/createRequestWithMetrics.es.js +123 -0
  26. package/lib/request/createRequestWithMetrics.js +128 -0
  27. package/lib/request/index.es.js +57 -0
  28. package/lib/request/index.js +65 -0
  29. package/lib/request/initRequestsMetrics.es.js +53 -0
  30. package/lib/request/initRequestsMetrics.js +61 -0
  31. package/lib/server.es.js +9 -469
  32. package/lib/server.js +9 -475
  33. package/package.json +19 -20
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var tslib = require('tslib');
6
+ var core = require('@tramvai/core');
7
+ var tokensMetrics = require('@tramvai/tokens-metrics');
8
+ var tokensCommon = require('@tramvai/tokens-common');
9
+ var noop = require('@tinkoff/utils/function/noop');
10
+ var https = require('https');
11
+ var http = require('http');
12
+ var createRequestWithMetrics = require('./createRequestWithMetrics.js');
13
+ var initRequestsMetrics = require('./initRequestsMetrics.js');
14
+ var MetricsServicesRegistry = require('./MetricsServicesRegistry.js');
15
+
16
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
17
+
18
+ var noop__default = /*#__PURE__*/_interopDefaultLegacy(noop);
19
+ var https__default = /*#__PURE__*/_interopDefaultLegacy(https);
20
+ var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
21
+
22
+ exports.RequestModule = class RequestModule {
23
+ };
24
+ exports.RequestModule = tslib.__decorate([
25
+ core.Module({
26
+ providers: [
27
+ {
28
+ provide: core.commandLineListTokens.init,
29
+ multi: true,
30
+ useFactory: ({ metrics, envManager, metricsServicesRegistry, metricsModuleConfig, }) => {
31
+ if (!metrics) {
32
+ return noop__default["default"];
33
+ }
34
+ return () => {
35
+ const env = envManager.getAll();
36
+ metricsServicesRegistry.registerEnv(env);
37
+ const getServiceName = metricsServicesRegistry.getServiceName.bind(metricsServicesRegistry);
38
+ initRequestsMetrics.initRequestsMetrics({
39
+ metrics,
40
+ getServiceName,
41
+ http: http__default["default"],
42
+ https: https__default["default"],
43
+ createRequestWithMetrics: createRequestWithMetrics.createRequestWithMetrics,
44
+ config: metricsModuleConfig,
45
+ });
46
+ };
47
+ },
48
+ deps: {
49
+ metrics: {
50
+ token: tokensMetrics.METRICS_MODULE_TOKEN,
51
+ optional: true,
52
+ },
53
+ metricsServicesRegistry: tokensMetrics.METRICS_SERVICES_REGISTRY_TOKEN,
54
+ envManager: tokensCommon.ENV_MANAGER_TOKEN,
55
+ metricsModuleConfig: tokensMetrics.METRICS_MODULE_CONFIG_TOKEN,
56
+ },
57
+ },
58
+ {
59
+ provide: tokensMetrics.METRICS_SERVICES_REGISTRY_TOKEN,
60
+ useClass: MetricsServicesRegistry.MetricsServicesRegistry,
61
+ scope: core.Scope.SINGLETON,
62
+ },
63
+ ],
64
+ })
65
+ ], exports.RequestModule);
@@ -0,0 +1,53 @@
1
+ import monkeypatch from '@tinkoff/monkeypatch';
2
+ import { DEFAULT_BUCKETS } from '../constants.es.js';
3
+
4
+ const initRequestsMetrics = ({ metrics, getServiceName, http, https, createRequestWithMetrics, config, }) => {
5
+ const metricsInstances = {
6
+ requestsTotal: metrics.counter({
7
+ name: 'http_sent_requests_total',
8
+ help: 'Number of requests sent',
9
+ labelNames: ['status', 'method', 'service'],
10
+ }),
11
+ requestsErrors: metrics.counter({
12
+ name: 'http_sent_requests_errors',
13
+ help: 'Number of requests that failed',
14
+ labelNames: ['status', 'method', 'service'],
15
+ }),
16
+ requestsDuration: metrics.histogram({
17
+ name: 'http_sent_requests_duration',
18
+ help: 'Execution time of the sent requests',
19
+ labelNames: ['status', 'method', 'service'],
20
+ buckets: DEFAULT_BUCKETS,
21
+ }),
22
+ dnsResolveDuration: metrics.histogram({
23
+ name: 'dns_resolve_duration',
24
+ help: 'Time for dns resolve of the outhgoing requests',
25
+ labelNames: ['service'],
26
+ buckets: DEFAULT_BUCKETS,
27
+ }),
28
+ tcpConnectDuration: metrics.histogram({
29
+ name: 'tcp_connect_duration',
30
+ help: 'Duration of tcp connect of the outgoing requests',
31
+ labelNames: ['service'],
32
+ buckets: DEFAULT_BUCKETS,
33
+ }),
34
+ tlsHandshakeDuration: metrics.histogram({
35
+ name: 'tls_handshake_duration',
36
+ help: 'Duration of tls handshake of the outgoing requests',
37
+ labelNames: ['service'],
38
+ buckets: DEFAULT_BUCKETS,
39
+ }),
40
+ };
41
+ monkeypatch({
42
+ obj: https,
43
+ method: 'request',
44
+ handler: createRequestWithMetrics({ metricsInstances, getServiceName, config }),
45
+ });
46
+ monkeypatch({
47
+ obj: http,
48
+ method: 'request',
49
+ handler: createRequestWithMetrics({ metricsInstances, getServiceName, config }),
50
+ });
51
+ };
52
+
53
+ export { initRequestsMetrics };
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var monkeypatch = require('@tinkoff/monkeypatch');
6
+ var constants = require('../constants.js');
7
+
8
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
+
10
+ var monkeypatch__default = /*#__PURE__*/_interopDefaultLegacy(monkeypatch);
11
+
12
+ const initRequestsMetrics = ({ metrics, getServiceName, http, https, createRequestWithMetrics, config, }) => {
13
+ const metricsInstances = {
14
+ requestsTotal: metrics.counter({
15
+ name: 'http_sent_requests_total',
16
+ help: 'Number of requests sent',
17
+ labelNames: ['status', 'method', 'service'],
18
+ }),
19
+ requestsErrors: metrics.counter({
20
+ name: 'http_sent_requests_errors',
21
+ help: 'Number of requests that failed',
22
+ labelNames: ['status', 'method', 'service'],
23
+ }),
24
+ requestsDuration: metrics.histogram({
25
+ name: 'http_sent_requests_duration',
26
+ help: 'Execution time of the sent requests',
27
+ labelNames: ['status', 'method', 'service'],
28
+ buckets: constants.DEFAULT_BUCKETS,
29
+ }),
30
+ dnsResolveDuration: metrics.histogram({
31
+ name: 'dns_resolve_duration',
32
+ help: 'Time for dns resolve of the outhgoing requests',
33
+ labelNames: ['service'],
34
+ buckets: constants.DEFAULT_BUCKETS,
35
+ }),
36
+ tcpConnectDuration: metrics.histogram({
37
+ name: 'tcp_connect_duration',
38
+ help: 'Duration of tcp connect of the outgoing requests',
39
+ labelNames: ['service'],
40
+ buckets: constants.DEFAULT_BUCKETS,
41
+ }),
42
+ tlsHandshakeDuration: metrics.histogram({
43
+ name: 'tls_handshake_duration',
44
+ help: 'Duration of tls handshake of the outgoing requests',
45
+ labelNames: ['service'],
46
+ buckets: constants.DEFAULT_BUCKETS,
47
+ }),
48
+ };
49
+ monkeypatch__default["default"]({
50
+ obj: https,
51
+ method: 'request',
52
+ handler: createRequestWithMetrics({ metricsInstances, getServiceName, config }),
53
+ });
54
+ monkeypatch__default["default"]({
55
+ obj: http,
56
+ method: 'request',
57
+ handler: createRequestWithMetrics({ metricsInstances, getServiceName, config }),
58
+ });
59
+ };
60
+
61
+ exports.initRequestsMetrics = initRequestsMetrics;
package/lib/server.es.js CHANGED
@@ -1,478 +1,18 @@
1
1
  import { __decorate } from 'tslib';
2
- import { Module, commandLineListTokens, Scope, provide } from '@tramvai/core';
2
+ import { Module, provide, Scope, commandLineListTokens } from '@tramvai/core';
3
3
  import { COMMAND_LINE_EXECUTION_END_TOKEN } from '@tramvai/tokens-core-private';
4
- import { SERVER_MODULE_PAPI_PUBLIC_ROUTE, UTILITY_SERVER_PATHS } from '@tramvai/tokens-server';
4
+ import { UTILITY_SERVER_PATHS } from '@tramvai/tokens-server';
5
5
  import { WEB_FASTIFY_APP_BEFORE_INIT_TOKEN, UTILITY_WEB_FASTIFY_APP_TOKEN, WEB_FASTIFY_APP_METRICS_TOKEN, WEB_FASTIFY_APP_TOKEN } from '@tramvai/tokens-server-private';
6
- import { METRICS_MODULE_TOKEN, METRICS_SERVICES_REGISTRY_TOKEN, METRICS_MODULE_CONFIG_TOKEN, REGISTER_INSTANT_METRIC_TOKEN } from '@tramvai/tokens-metrics';
6
+ import { METRICS_MODULE_CONFIG_TOKEN, METRICS_MODULE_TOKEN } from '@tramvai/tokens-metrics';
7
7
  export * from '@tramvai/tokens-metrics';
8
8
  import { fastifyMeasureRequests } from '@tinkoff/measure-fastify-requests';
9
9
  import { Registry, collectDefaultMetrics, Counter, Gauge, Histogram, Summary } from 'prom-client';
10
10
  import flatten from '@tinkoff/utils/array/flatten';
11
- import { ENV_MANAGER_TOKEN, COMBINE_REDUCERS, LOGGER_TOKEN, CONTEXT_TOKEN } from '@tramvai/tokens-common';
12
- import noop from '@tinkoff/utils/function/noop';
13
- import https from 'https';
14
- import http from 'http';
15
- import { format } from '@tinkoff/url';
16
- import monkeypatch from '@tinkoff/monkeypatch';
17
- import isString from '@tinkoff/utils/is/string';
18
- import { createPapiMethod } from '@tramvai/papi';
19
- import fromPairs from '@tinkoff/utils/object/fromPairs';
20
- import { createEvent, createReducer } from '@tramvai/state';
21
-
22
- // https://nodejs.org/api/errors.html#nodejs-error-codes - Common system errors possible for net/http/dns
23
- const POSSIBLE_ERRORS = [
24
- 'EADDRINUSE',
25
- 'ECONNREFUSED',
26
- 'ECONNRESET',
27
- 'ENOTFOUND',
28
- 'EPIPE',
29
- 'ETIMEDOUT',
30
- ];
31
- const getUrlAndOptions = (args) => {
32
- let url;
33
- let options;
34
- // У request первый аргумент либо урл либо объект опций, кейс когда первого аргумента нет не валиден
35
- const isUrlStringFirst = args[0].constructor === String;
36
- const isUrlObjectFirst = args[0].constructor === URL;
37
- const isOptionsFirst = !isUrlStringFirst && !isUrlObjectFirst;
38
- const isOptionsSecond = !isOptionsFirst && !(args[0] instanceof Function);
39
- if (isUrlStringFirst) {
40
- [url] = args;
41
- }
42
- if (isUrlObjectFirst) {
43
- url = format(args[0]);
44
- }
45
- if (isOptionsFirst) {
46
- [options] = args;
47
- // Тут учитываем случай если передаётся не href в options, а отдельно protocol, host, port, path
48
- if (options.href) {
49
- url = options.href;
50
- }
51
- else {
52
- const urlString = format({
53
- protocol: options.protocol,
54
- host: options.hostname || options.host,
55
- port: options.port,
56
- pathname: options.path,
57
- });
58
- // format где-то внутри делает encodeURIComponent и из-за этого потом не может обрезать query
59
- try {
60
- url = decodeURIComponent(urlString);
61
- }
62
- catch {
63
- url = urlString;
64
- }
65
- }
66
- }
67
- if (isOptionsSecond) {
68
- [, options] = args;
69
- }
70
- const parsedUrl = new URL(url);
71
- const urlWOQuery = parsedUrl.origin + parsedUrl.pathname;
72
- return [urlWOQuery, options || {}, parsedUrl];
73
- };
74
- // in seconds
75
- const getDuration = (current, prev) =>
76
- // max to avoid negative values and turn that into zero
77
- prev === 0 ? 0 : Math.max((current - prev) / 1000, 0);
78
- const createRequestWithMetrics = ({ metricsInstances: { requestsTotal, requestsErrors, requestsDuration, dnsResolveDuration, tcpConnectDuration, tlsHandshakeDuration, }, getServiceName, config, }) => {
79
- const socketSet = new WeakSet();
80
- return function requestWithMetrics(originalRequest, ...args) {
81
- const [url, options] = getUrlAndOptions(args);
82
- const serviceName = getServiceName(url);
83
- const req = originalRequest.apply(this, args);
84
- const timerDone = requestsDuration.startTimer();
85
- const labelsValues = {
86
- method: options.method || 'unknown',
87
- service: serviceName || new URL(url).origin || 'unknown',
88
- status: 'unknown',
89
- };
90
- req.on('response', (res) => {
91
- labelsValues.status = res.statusCode.toString();
92
- if (res.statusCode >= 400) {
93
- requestsErrors.inc(labelsValues);
94
- }
95
- requestsTotal.inc(labelsValues);
96
- timerDone(labelsValues);
97
- });
98
- req.on('error', (e) => {
99
- if (POSSIBLE_ERRORS.includes(e === null || e === void 0 ? void 0 : e.code)) {
100
- labelsValues.status = req.aborted ? 'aborted' : e.code;
101
- }
102
- requestsTotal.inc(labelsValues);
103
- requestsErrors.inc(labelsValues);
104
- timerDone(labelsValues);
105
- });
106
- if (config.enableConnectionResolveMetrics) {
107
- req.on('socket', (socket) => {
108
- // due to keep-alive tcp option sockets might be reused
109
- // ignore them because they have already emitted events we are interested in
110
- if (socketSet.has(socket)) {
111
- return;
112
- }
113
- socketSet.add(socket);
114
- const timings = {
115
- start: Date.now(),
116
- lookupEnd: 0,
117
- connectEnd: 0,
118
- secureConnectEnd: 0,
119
- };
120
- const { service } = labelsValues;
121
- socket.on('lookup', () => {
122
- timings.lookupEnd = Date.now();
123
- dnsResolveDuration.observe({ service }, getDuration(timings.lookupEnd, timings.start));
124
- });
125
- socket.on('connect', () => {
126
- timings.connectEnd = Date.now();
127
- tcpConnectDuration.observe({ service }, getDuration(timings.connectEnd, timings.lookupEnd));
128
- });
129
- socket.on('secureConnect', () => {
130
- timings.secureConnectEnd = Date.now();
131
- tlsHandshakeDuration.observe({ service }, getDuration(timings.secureConnectEnd, timings.connectEnd));
132
- });
133
- socket.on('close', () => {
134
- socketSet.delete(socket);
135
- });
136
- });
137
- }
138
- return req;
139
- };
140
- };
141
-
142
- const DEFAULT_BUCKETS = [0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 20, 40, 60];
143
-
144
- const initRequestsMetrics = ({ metrics, getServiceName, http, https, createRequestWithMetrics, config, }) => {
145
- const metricsInstances = {
146
- requestsTotal: metrics.counter({
147
- name: 'http_sent_requests_total',
148
- help: 'Number of requests sent',
149
- labelNames: ['status', 'method', 'service'],
150
- }),
151
- requestsErrors: metrics.counter({
152
- name: 'http_sent_requests_errors',
153
- help: 'Number of requests that failed',
154
- labelNames: ['status', 'method', 'service'],
155
- }),
156
- requestsDuration: metrics.histogram({
157
- name: 'http_sent_requests_duration',
158
- help: 'Execution time of the sent requests',
159
- labelNames: ['status', 'method', 'service'],
160
- buckets: DEFAULT_BUCKETS,
161
- }),
162
- dnsResolveDuration: metrics.histogram({
163
- name: 'dns_resolve_duration',
164
- help: 'Time for dns resolve of the outhgoing requests',
165
- labelNames: ['service'],
166
- buckets: DEFAULT_BUCKETS,
167
- }),
168
- tcpConnectDuration: metrics.histogram({
169
- name: 'tcp_connect_duration',
170
- help: 'Duration of tcp connect of the outgoing requests',
171
- labelNames: ['service'],
172
- buckets: DEFAULT_BUCKETS,
173
- }),
174
- tlsHandshakeDuration: metrics.histogram({
175
- name: 'tls_handshake_duration',
176
- help: 'Duration of tls handshake of the outgoing requests',
177
- labelNames: ['service'],
178
- buckets: DEFAULT_BUCKETS,
179
- }),
180
- };
181
- monkeypatch({
182
- obj: https,
183
- method: 'request',
184
- handler: createRequestWithMetrics({ metricsInstances, getServiceName, config }),
185
- });
186
- monkeypatch({
187
- obj: http,
188
- method: 'request',
189
- handler: createRequestWithMetrics({ metricsInstances, getServiceName, config }),
190
- });
191
- };
192
-
193
- // Дерево использует подход структуры данных trie для прямого доступа к serviceName, но в отличие от
194
- // trie возвращает не все значения соответствующие префиксу, а значение соответствующее самому
195
- // длинному ключу в дереве который является подстрокой входной строки
196
- class PrefixTree {
197
- constructor(options = {}) {
198
- this.index = Object.create(null);
199
- this.delimiter = options.delimiter || '';
200
- }
201
- // На случай если value не примитивные значения есть возможность передать функцию и там как угодно
202
- // модифицировать объект
203
- set(key, valueOrUpdateFn) {
204
- let tree = this.index;
205
- const parts = key.split(this.delimiter);
206
- do {
207
- const letter = parts.shift();
208
- if (letter === '')
209
- continue;
210
- if (!tree[letter]) {
211
- tree[letter] = Object.create(null);
212
- }
213
- tree = tree[letter];
214
- } while (parts.length);
215
- if (valueOrUpdateFn instanceof Function) {
216
- tree.value = valueOrUpdateFn(tree.value);
217
- }
218
- else {
219
- tree.value = valueOrUpdateFn;
220
- }
221
- }
222
- get(key) {
223
- let tree = this.index;
224
- const parts = key.split(this.delimiter);
225
- let prevTree;
226
- do {
227
- const letter = parts.shift();
228
- if (letter === '')
229
- continue;
230
- prevTree = tree;
231
- tree = tree[letter];
232
- } while (parts.length && tree);
233
- if (tree) {
234
- return tree.value;
235
- }
236
- return prevTree.value;
237
- }
238
- }
239
-
240
- const NO_PROTOCOL = 'NO PROTOCOL';
241
- const PROTOCOL_REGEX = /^([a-z0-9.+-]+:)/i;
242
- const splitProtocolAndUrl = (url) => {
243
- // Регулярка используется потому что протокол обязателен и класс URL не распарсит такую строку
244
- const urlMatches = url.match(PROTOCOL_REGEX);
245
- const protocol = urlMatches && urlMatches[0];
246
- // Под + 2 тут подразумевается два слеша после протокола например для http: обрежется http://
247
- const urlWOProtocol = protocol ? url.slice(protocol.length + 2) : url;
248
- return [protocol, urlWOProtocol];
249
- };
250
- class MetricsServicesRegistry {
251
- constructor() {
252
- this.registryPrefixTree = new PrefixTree({
253
- delimiter: '/',
254
- });
255
- }
256
- registerEnv(env) {
257
- Object.keys(env).forEach((name) => {
258
- // В env могут быть undefined, и number, т.к. это явно не урлы, просто пропускаем
259
- if (isString(env[name])) {
260
- this.register(env[name], name);
261
- }
262
- });
263
- }
264
- register(url, serviceName) {
265
- if (!url) {
266
- return;
267
- }
268
- const [protocol, urlWOProtocol] = splitProtocolAndUrl(url);
269
- // Некоторые модули не хранят инфу о протоколе, потому что tinkoff-request сам подставляет протокол.
270
- // В результате при поиске префиксное дерево не отрабатывает.
271
- // предусматриваем этот случай добавляя инфу о том для какого протокола храним имя сервиса.
272
- this.registryPrefixTree.set(urlWOProtocol, (value) => ({
273
- ...(value || {}),
274
- [protocol || NO_PROTOCOL]: serviceName,
275
- }));
276
- }
277
- getServiceName(url) {
278
- if (!url) {
279
- return undefined;
280
- }
281
- const [protocol, urlWOProtocol] = splitProtocolAndUrl(url);
282
- const treeValue = this.registryPrefixTree.get(urlWOProtocol);
283
- if (!treeValue) {
284
- return undefined;
285
- }
286
- // Когда урл запросен из регистри, мы не знаем был ли он добавлен с протоколом, поэтому
287
- // проверяем оба варианта
288
- return treeValue[protocol] || treeValue[NO_PROTOCOL];
289
- }
290
- }
291
-
292
- let RequestModule = class RequestModule {
293
- };
294
- RequestModule = __decorate([
295
- Module({
296
- providers: [
297
- {
298
- provide: commandLineListTokens.init,
299
- multi: true,
300
- useFactory: ({ metrics, envManager, metricsServicesRegistry, metricsModuleConfig, }) => {
301
- if (!metrics) {
302
- return noop;
303
- }
304
- return () => {
305
- const env = envManager.getAll();
306
- metricsServicesRegistry.registerEnv(env);
307
- const getServiceName = metricsServicesRegistry.getServiceName.bind(metricsServicesRegistry);
308
- initRequestsMetrics({
309
- metrics,
310
- getServiceName,
311
- http,
312
- https,
313
- createRequestWithMetrics,
314
- config: metricsModuleConfig,
315
- });
316
- };
317
- },
318
- deps: {
319
- metrics: {
320
- token: METRICS_MODULE_TOKEN,
321
- optional: true,
322
- },
323
- metricsServicesRegistry: METRICS_SERVICES_REGISTRY_TOKEN,
324
- envManager: ENV_MANAGER_TOKEN,
325
- metricsModuleConfig: METRICS_MODULE_CONFIG_TOKEN,
326
- },
327
- },
328
- {
329
- provide: METRICS_SERVICES_REGISTRY_TOKEN,
330
- useClass: MetricsServicesRegistry,
331
- scope: Scope.SINGLETON,
332
- },
333
- ],
334
- })
335
- ], RequestModule);
336
-
337
- const setInstantMetrics = createEvent('set instant metrics map');
338
- const MetricsStore = createReducer('instantMetrics', { instantMetricsMap: {} }).on(setInstantMetrics, (_prevState, nextState) => {
339
- return nextState;
340
- });
341
-
342
- const sharedProviders = [
343
- {
344
- provide: COMBINE_REDUCERS,
345
- multi: true,
346
- useValue: [MetricsStore],
347
- },
348
- ];
349
-
350
- let InstantMetricsModule = class InstantMetricsModule {
351
- };
352
- InstantMetricsModule = __decorate([
353
- Module({
354
- providers: [
355
- ...sharedProviders,
356
- {
357
- provide: SERVER_MODULE_PAPI_PUBLIC_ROUTE,
358
- multi: true,
359
- useFactory({ metrics, logger, instantMetrics, }) {
360
- const log = logger('instantmetrics:papi');
361
- const instantMetricsMap = fromPairs(instantMetrics || []);
362
- return createPapiMethod({
363
- method: 'post',
364
- path: '/metrics/:metric',
365
- options: {
366
- schema: {
367
- body: {
368
- type: 'object',
369
- properties: {
370
- value: {
371
- type: 'number',
372
- minimum: 0,
373
- },
374
- },
375
- additionalProperties: false,
376
- },
377
- },
378
- },
379
- async handler({ params: { metric }, body, responseManager }) {
380
- if (!instantMetricsMap[metric]) {
381
- log.error({
382
- event: 'client-instant-metric-mismatch',
383
- metricName: metric,
384
- error: new Error(`No instant metric instance found with name: ${metric}`),
385
- });
386
- responseManager.setStatus(404);
387
- responseManager.setBody({
388
- resultCode: 'NOT_FOUND',
389
- errorMessage: 'metric not found',
390
- });
391
- return;
392
- }
393
- instantMetricsMap[metric].inc(body === null || body === void 0 ? void 0 : body.value);
394
- return { status: 'ok' };
395
- },
396
- });
397
- },
398
- deps: {
399
- metrics: METRICS_MODULE_TOKEN,
400
- logger: LOGGER_TOKEN,
401
- instantMetrics: {
402
- token: REGISTER_INSTANT_METRIC_TOKEN,
403
- multi: true,
404
- optional: true,
405
- },
406
- },
407
- },
408
- {
409
- provide: commandLineListTokens.customerStart,
410
- multi: true,
411
- useFactory({ instantMetrics, context, }) {
412
- return async () => {
413
- if (!instantMetrics) {
414
- return;
415
- }
416
- const instantMetricsMap = instantMetrics.reduce((acc, [metricName]) => {
417
- acc[metricName] = true;
418
- return acc;
419
- }, {});
420
- await context.dispatch(setInstantMetrics({ instantMetricsMap }));
421
- };
422
- },
423
- deps: {
424
- context: CONTEXT_TOKEN,
425
- instantMetrics: {
426
- token: REGISTER_INSTANT_METRIC_TOKEN,
427
- multi: true,
428
- optional: true,
429
- },
430
- },
431
- },
432
- ],
433
- })
434
- ], InstantMetricsModule);
435
-
436
- const NODEJS_EVENTLOOP_LAG = 'nodejs_eventloop_setinterval_lag_seconds';
437
- function startEventLoopLagMeasure(histogram) {
438
- let start = process.hrtime();
439
- const interval = 100;
440
- setInterval(() => {
441
- const delta = process.hrtime(start);
442
- const nanosec = delta[0] * 1e9 + delta[1];
443
- const ms = nanosec / 1e6;
444
- const lag = ms - interval;
445
- histogram.observe(lag / 1e3);
446
- start = process.hrtime();
447
- }, interval).unref();
448
- }
449
- const eventLoopMetrics = (metrics) => {
450
- const histogram = metrics.histogram({
451
- name: NODEJS_EVENTLOOP_LAG,
452
- help: 'Lag of event loop in seconds (setInterval based).',
453
- buckets: [0.02, 0.1, 0.2, 0.5, 1, 3, 5, 7.5, 10],
454
- });
455
- startEventLoopLagMeasure(histogram);
456
- };
457
-
458
- const commandLineMetrics = (metrics) => {
459
- const metricsInstance = metrics.histogram({
460
- name: `command_line_runner_execution_time`,
461
- help: 'Command line processing duration',
462
- labelNames: ['line'],
463
- buckets: DEFAULT_BUCKETS,
464
- });
465
- return (di, type, status, timingInfo) => {
466
- for (const line in timingInfo) {
467
- const info = timingInfo[line];
468
- if (info.end) {
469
- const durationInMs = info.end - info.start;
470
- const durationInSec = durationInMs / 1000;
471
- metricsInstance.observe({ line }, durationInSec);
472
- }
473
- }
474
- };
475
- };
11
+ import { RequestModule } from './request/index.es.js';
12
+ import { InstantMetricsModule } from './instantMetrics/server.es.js';
13
+ import { eventLoopMetrics } from './metrics/eventLoop.es.js';
14
+ import { commandLineMetrics } from './metrics/commandLine.es.js';
15
+ export { getUrlAndOptions } from './request/createRequestWithMetrics.es.js';
476
16
 
477
17
  let MetricsModule = class MetricsModule {
478
18
  };
@@ -590,4 +130,4 @@ MetricsModule = __decorate([
590
130
  })
591
131
  ], MetricsModule);
592
132
 
593
- export { MetricsModule, getUrlAndOptions };
133
+ export { MetricsModule };