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