@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/browser.js CHANGED
@@ -1,164 +1,13 @@
1
1
  import { __decorate } from 'tslib';
2
- import { Module, commandLineListTokens, Scope } from '@tramvai/core';
3
- import { COMBINE_REDUCERS, CONTEXT_TOKEN, LOGGER_TOKEN } from '@tramvai/tokens-common';
2
+ import { Module, Scope, commandLineListTokens } from '@tramvai/core';
3
+ import { LOGGER_TOKEN } from '@tramvai/tokens-common';
4
4
  import { METRICS_MODULE_TOKEN } from '@tramvai/tokens-metrics';
5
5
  export * from '@tramvai/tokens-metrics';
6
6
  import { browserTimings } from '@tinkoff/browser-timings';
7
- import { Histogram, Summary, Gauge, Counter } from '@tinkoff/metrics-noop';
7
+ import { Counter, Gauge, Histogram, Summary } from '@tinkoff/metrics-noop';
8
8
  import { PAGE_SERVICE_TOKEN } from '@tramvai/tokens-router';
9
- import { PAPI_SERVICE } from '@tramvai/tokens-http-client';
10
- import { RemoteReporter } from '@tinkoff/logger';
11
- import { createEvent, createReducer } from '@tramvai/state';
12
-
13
- const setInstantMetrics = createEvent('set instant metrics map');
14
- const MetricsStore = createReducer('instantMetrics', { instantMetricsMap: {} }).on(setInstantMetrics, (_prevState, nextState) => {
15
- return nextState;
16
- });
17
-
18
- const sharedProviders = [
19
- {
20
- provide: COMBINE_REDUCERS,
21
- multi: true,
22
- useValue: [MetricsStore],
23
- },
24
- ];
25
-
26
- let InstantMetricsModule = class InstantMetricsModule {
27
- };
28
- InstantMetricsModule = __decorate([
29
- Module({
30
- providers: [
31
- ...sharedProviders,
32
- {
33
- // При такой схеме подключения отправка instant метрик заработает только после этого
34
- // провайдера, но подлючить через LOGGER_INIT_HOOK не представляется возможным потому что
35
- // возникает циклическая зависимость контекст -> логгер -> хук метрик -> контекст
36
- provide: commandLineListTokens.init,
37
- scope: Scope.SINGLETON,
38
- multi: true,
39
- useFactory({ logger, papiService, context, }) {
40
- if (!papiService) {
41
- return () => { };
42
- }
43
- const validMetricsMap = context.getStore('instantMetrics').getState().instantMetricsMap;
44
- const instantMetricsReporter = new RemoteReporter({
45
- requestCount: 1,
46
- emitLevels: {
47
- trace: true,
48
- debug: true,
49
- info: true,
50
- warn: true,
51
- error: true,
52
- fatal: true,
53
- },
54
- makeRequest(logObject) {
55
- if (validMetricsMap[logObject.event]) {
56
- return papiService
57
- .request({
58
- path: `metrics/${logObject.event}`,
59
- method: 'post',
60
- payload: logObject.value
61
- ? {
62
- value: logObject.value,
63
- }
64
- : {},
65
- })
66
- .then(({ payload }) => payload);
67
- }
68
- return Promise.resolve();
69
- },
70
- });
71
- return () => {
72
- logger.addBeforeReporter(instantMetricsReporter);
73
- };
74
- },
75
- deps: {
76
- papiService: {
77
- token: PAPI_SERVICE,
78
- optional: true,
79
- },
80
- context: CONTEXT_TOKEN,
81
- logger: LOGGER_TOKEN,
82
- },
83
- },
84
- ],
85
- })
86
- ], InstantMetricsModule);
87
-
88
- function startMeasure(markName, uniqueMarkId) {
89
- const uniqueMarkName = `${markName}:${uniqueMarkId}`;
90
- performance.mark(uniqueMarkName);
91
- function endMeasure(measureName) {
92
- try {
93
- performance.measure(measureName || markName, uniqueMarkName);
94
- }
95
- catch (e) { }
96
- performance.clearMarks(uniqueMarkName);
97
- }
98
- return endMeasure;
99
- }
100
-
101
- const supportsUserTiming = typeof performance !== 'undefined' &&
102
- typeof performance.mark === 'function' &&
103
- typeof performance.clearMarks === 'function' &&
104
- typeof performance.measure === 'function' &&
105
- typeof performance.clearMeasures === 'function';
106
-
107
- let idCounter = 0;
108
- function uniqueId() {
109
- // eslint-disable-next-line no-plusplus
110
- return ++idCounter;
111
- }
112
-
113
- function startMeasurePerformance(name, startLabels = {}) {
114
- if (!supportsUserTiming) {
115
- return () => { };
116
- }
117
- const endMeasure = startMeasure(name, uniqueId());
118
- return (endLabels = {}) => {
119
- const labels = { ...startLabels, ...endLabels };
120
- const labelsNames = Object.keys(labels)
121
- .map((key) => `${key}="${labels[key]}"`)
122
- .join(',');
123
- endMeasure(labelsNames && `${name}{${labelsNames}}`);
124
- };
125
- }
126
- class PerfHistogram extends Histogram {
127
- constructor(configurator) {
128
- super(configurator);
129
- this.name = configurator.name;
130
- }
131
- startTimer(startLabels) {
132
- const endMeasure = startMeasurePerformance(this.name, startLabels);
133
- return (endLabels) => {
134
- endMeasure(endLabels);
135
- };
136
- }
137
- }
138
- class PerfSummary extends Summary {
139
- constructor(configurator) {
140
- super(configurator);
141
- this.name = configurator.name;
142
- }
143
- startTimer() {
144
- const endMeasure = startMeasurePerformance(this.name);
145
- return (endLabels) => {
146
- endMeasure(endLabels);
147
- };
148
- }
149
- }
150
- class PerfGauge extends Gauge {
151
- constructor(configurator) {
152
- super(configurator);
153
- this.name = configurator.name;
154
- }
155
- startTimer(startLabels) {
156
- const endMeasure = startMeasurePerformance(this.name, startLabels);
157
- return (endLabels) => {
158
- endMeasure(endLabels);
159
- };
160
- }
161
- }
9
+ import { InstantMetricsModule } from './instantMetrics/browser.browser.js';
10
+ import { PerfGauge, PerfHistogram, PerfSummary } from './performance-devtools/PerfMetrics.browser.js';
162
11
 
163
12
  let MetricsModule = class MetricsModule {
164
13
  };
@@ -0,0 +1,3 @@
1
+ const DEFAULT_BUCKETS = [0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 20, 40, 60];
2
+
3
+ export { DEFAULT_BUCKETS };
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const DEFAULT_BUCKETS = [0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 20, 40, 60];
6
+
7
+ exports.DEFAULT_BUCKETS = DEFAULT_BUCKETS;
@@ -0,0 +1,70 @@
1
+ import { __decorate } from 'tslib';
2
+ import { Module, commandLineListTokens, Scope } from '@tramvai/core';
3
+ import { CONTEXT_TOKEN, LOGGER_TOKEN } from '@tramvai/tokens-common';
4
+ import { PAPI_SERVICE } from '@tramvai/tokens-http-client';
5
+ import { RemoteReporter } from '@tinkoff/logger';
6
+ import { sharedProviders } from './shared.browser.js';
7
+
8
+ let InstantMetricsModule = class InstantMetricsModule {
9
+ };
10
+ InstantMetricsModule = __decorate([
11
+ Module({
12
+ providers: [
13
+ ...sharedProviders,
14
+ {
15
+ // При такой схеме подключения отправка instant метрик заработает только после этого
16
+ // провайдера, но подлючить через LOGGER_INIT_HOOK не представляется возможным потому что
17
+ // возникает циклическая зависимость контекст -> логгер -> хук метрик -> контекст
18
+ provide: commandLineListTokens.init,
19
+ scope: Scope.SINGLETON,
20
+ multi: true,
21
+ useFactory({ logger, papiService, context, }) {
22
+ if (!papiService) {
23
+ return () => { };
24
+ }
25
+ const validMetricsMap = context.getStore('instantMetrics').getState().instantMetricsMap;
26
+ const instantMetricsReporter = new RemoteReporter({
27
+ requestCount: 1,
28
+ emitLevels: {
29
+ trace: true,
30
+ debug: true,
31
+ info: true,
32
+ warn: true,
33
+ error: true,
34
+ fatal: true,
35
+ },
36
+ makeRequest(logObject) {
37
+ if (validMetricsMap[logObject.event]) {
38
+ return papiService
39
+ .request({
40
+ path: `metrics/${logObject.event}`,
41
+ method: 'post',
42
+ payload: logObject.value
43
+ ? {
44
+ value: logObject.value,
45
+ }
46
+ : {},
47
+ })
48
+ .then(({ payload }) => payload);
49
+ }
50
+ return Promise.resolve();
51
+ },
52
+ });
53
+ return () => {
54
+ logger.addBeforeReporter(instantMetricsReporter);
55
+ };
56
+ },
57
+ deps: {
58
+ papiService: {
59
+ token: PAPI_SERVICE,
60
+ optional: true,
61
+ },
62
+ context: CONTEXT_TOKEN,
63
+ logger: LOGGER_TOKEN,
64
+ },
65
+ },
66
+ ],
67
+ })
68
+ ], InstantMetricsModule);
69
+
70
+ export { InstantMetricsModule };
@@ -0,0 +1,97 @@
1
+ import { __decorate } from 'tslib';
2
+ import { Module, commandLineListTokens } from '@tramvai/core';
3
+ import { SERVER_MODULE_PAPI_PUBLIC_ROUTE } from '@tramvai/tokens-server';
4
+ import { createPapiMethod } from '@tramvai/papi';
5
+ import { METRICS_MODULE_TOKEN, REGISTER_INSTANT_METRIC_TOKEN } from '@tramvai/tokens-metrics';
6
+ import { LOGGER_TOKEN, CONTEXT_TOKEN } from '@tramvai/tokens-common';
7
+ import fromPairs from '@tinkoff/utils/object/fromPairs';
8
+ import { sharedProviders } from './shared.es.js';
9
+ import { setInstantMetrics } from './store.es.js';
10
+
11
+ let InstantMetricsModule = class InstantMetricsModule {
12
+ };
13
+ InstantMetricsModule = __decorate([
14
+ Module({
15
+ providers: [
16
+ ...sharedProviders,
17
+ {
18
+ provide: SERVER_MODULE_PAPI_PUBLIC_ROUTE,
19
+ multi: true,
20
+ useFactory({ metrics, logger, instantMetrics, }) {
21
+ const log = logger('instantmetrics:papi');
22
+ const instantMetricsMap = fromPairs(instantMetrics || []);
23
+ return createPapiMethod({
24
+ method: 'post',
25
+ path: '/metrics/:metric',
26
+ options: {
27
+ schema: {
28
+ body: {
29
+ type: 'object',
30
+ properties: {
31
+ value: {
32
+ type: 'number',
33
+ minimum: 0,
34
+ },
35
+ },
36
+ additionalProperties: false,
37
+ },
38
+ },
39
+ },
40
+ async handler({ params: { metric }, body, responseManager }) {
41
+ if (!instantMetricsMap[metric]) {
42
+ log.error({
43
+ event: 'client-instant-metric-mismatch',
44
+ metricName: metric,
45
+ error: new Error(`No instant metric instance found with name: ${metric}`),
46
+ });
47
+ responseManager.setStatus(404);
48
+ responseManager.setBody({
49
+ resultCode: 'NOT_FOUND',
50
+ errorMessage: 'metric not found',
51
+ });
52
+ return;
53
+ }
54
+ instantMetricsMap[metric].inc(body === null || body === void 0 ? void 0 : body.value);
55
+ return { status: 'ok' };
56
+ },
57
+ });
58
+ },
59
+ deps: {
60
+ metrics: METRICS_MODULE_TOKEN,
61
+ logger: LOGGER_TOKEN,
62
+ instantMetrics: {
63
+ token: REGISTER_INSTANT_METRIC_TOKEN,
64
+ multi: true,
65
+ optional: true,
66
+ },
67
+ },
68
+ },
69
+ {
70
+ provide: commandLineListTokens.customerStart,
71
+ multi: true,
72
+ useFactory({ instantMetrics, context, }) {
73
+ return async () => {
74
+ if (!instantMetrics) {
75
+ return;
76
+ }
77
+ const instantMetricsMap = instantMetrics.reduce((acc, [metricName]) => {
78
+ acc[metricName] = true;
79
+ return acc;
80
+ }, {});
81
+ await context.dispatch(setInstantMetrics({ instantMetricsMap }));
82
+ };
83
+ },
84
+ deps: {
85
+ context: CONTEXT_TOKEN,
86
+ instantMetrics: {
87
+ token: REGISTER_INSTANT_METRIC_TOKEN,
88
+ multi: true,
89
+ optional: true,
90
+ },
91
+ },
92
+ },
93
+ ],
94
+ })
95
+ ], InstantMetricsModule);
96
+
97
+ export { InstantMetricsModule };
@@ -0,0 +1,103 @@
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 tokensServer = require('@tramvai/tokens-server');
8
+ var papi = require('@tramvai/papi');
9
+ var tokensMetrics = require('@tramvai/tokens-metrics');
10
+ var tokensCommon = require('@tramvai/tokens-common');
11
+ var fromPairs = require('@tinkoff/utils/object/fromPairs');
12
+ var shared = require('./shared.js');
13
+ var store = require('./store.js');
14
+
15
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
16
+
17
+ var fromPairs__default = /*#__PURE__*/_interopDefaultLegacy(fromPairs);
18
+
19
+ exports.InstantMetricsModule = class InstantMetricsModule {
20
+ };
21
+ exports.InstantMetricsModule = tslib.__decorate([
22
+ core.Module({
23
+ providers: [
24
+ ...shared.sharedProviders,
25
+ {
26
+ provide: tokensServer.SERVER_MODULE_PAPI_PUBLIC_ROUTE,
27
+ multi: true,
28
+ useFactory({ metrics, logger, instantMetrics, }) {
29
+ const log = logger('instantmetrics:papi');
30
+ const instantMetricsMap = fromPairs__default["default"](instantMetrics || []);
31
+ return papi.createPapiMethod({
32
+ method: 'post',
33
+ path: '/metrics/:metric',
34
+ options: {
35
+ schema: {
36
+ body: {
37
+ type: 'object',
38
+ properties: {
39
+ value: {
40
+ type: 'number',
41
+ minimum: 0,
42
+ },
43
+ },
44
+ additionalProperties: false,
45
+ },
46
+ },
47
+ },
48
+ async handler({ params: { metric }, body, responseManager }) {
49
+ if (!instantMetricsMap[metric]) {
50
+ log.error({
51
+ event: 'client-instant-metric-mismatch',
52
+ metricName: metric,
53
+ error: new Error(`No instant metric instance found with name: ${metric}`),
54
+ });
55
+ responseManager.setStatus(404);
56
+ responseManager.setBody({
57
+ resultCode: 'NOT_FOUND',
58
+ errorMessage: 'metric not found',
59
+ });
60
+ return;
61
+ }
62
+ instantMetricsMap[metric].inc(body === null || body === void 0 ? void 0 : body.value);
63
+ return { status: 'ok' };
64
+ },
65
+ });
66
+ },
67
+ deps: {
68
+ metrics: tokensMetrics.METRICS_MODULE_TOKEN,
69
+ logger: tokensCommon.LOGGER_TOKEN,
70
+ instantMetrics: {
71
+ token: tokensMetrics.REGISTER_INSTANT_METRIC_TOKEN,
72
+ multi: true,
73
+ optional: true,
74
+ },
75
+ },
76
+ },
77
+ {
78
+ provide: core.commandLineListTokens.customerStart,
79
+ multi: true,
80
+ useFactory({ instantMetrics, context, }) {
81
+ return async () => {
82
+ if (!instantMetrics) {
83
+ return;
84
+ }
85
+ const instantMetricsMap = instantMetrics.reduce((acc, [metricName]) => {
86
+ acc[metricName] = true;
87
+ return acc;
88
+ }, {});
89
+ await context.dispatch(store.setInstantMetrics({ instantMetricsMap }));
90
+ };
91
+ },
92
+ deps: {
93
+ context: tokensCommon.CONTEXT_TOKEN,
94
+ instantMetrics: {
95
+ token: tokensMetrics.REGISTER_INSTANT_METRIC_TOKEN,
96
+ multi: true,
97
+ optional: true,
98
+ },
99
+ },
100
+ },
101
+ ],
102
+ })
103
+ ], exports.InstantMetricsModule);
@@ -0,0 +1,12 @@
1
+ import { COMBINE_REDUCERS } from '@tramvai/tokens-common';
2
+ import { MetricsStore } from './store.browser.js';
3
+
4
+ const sharedProviders = [
5
+ {
6
+ provide: COMBINE_REDUCERS,
7
+ multi: true,
8
+ useValue: [MetricsStore],
9
+ },
10
+ ];
11
+
12
+ export { sharedProviders };
@@ -0,0 +1,12 @@
1
+ import { COMBINE_REDUCERS } from '@tramvai/tokens-common';
2
+ import { MetricsStore } from './store.es.js';
3
+
4
+ const sharedProviders = [
5
+ {
6
+ provide: COMBINE_REDUCERS,
7
+ multi: true,
8
+ useValue: [MetricsStore],
9
+ },
10
+ ];
11
+
12
+ export { sharedProviders };
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var tokensCommon = require('@tramvai/tokens-common');
6
+ var store = require('./store.js');
7
+
8
+ const sharedProviders = [
9
+ {
10
+ provide: tokensCommon.COMBINE_REDUCERS,
11
+ multi: true,
12
+ useValue: [store.MetricsStore],
13
+ },
14
+ ];
15
+
16
+ exports.sharedProviders = sharedProviders;
@@ -0,0 +1,8 @@
1
+ import { createEvent, createReducer } from '@tramvai/state';
2
+
3
+ const setInstantMetrics = createEvent('set instant metrics map');
4
+ const MetricsStore = createReducer('instantMetrics', { instantMetricsMap: {} }).on(setInstantMetrics, (_prevState, nextState) => {
5
+ return nextState;
6
+ });
7
+
8
+ export { MetricsStore, setInstantMetrics };
@@ -0,0 +1,8 @@
1
+ import { createEvent, createReducer } from '@tramvai/state';
2
+
3
+ const setInstantMetrics = createEvent('set instant metrics map');
4
+ const MetricsStore = createReducer('instantMetrics', { instantMetricsMap: {} }).on(setInstantMetrics, (_prevState, nextState) => {
5
+ return nextState;
6
+ });
7
+
8
+ export { MetricsStore, setInstantMetrics };
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var state = require('@tramvai/state');
6
+
7
+ const setInstantMetrics = state.createEvent('set instant metrics map');
8
+ const MetricsStore = state.createReducer('instantMetrics', { instantMetricsMap: {} }).on(setInstantMetrics, (_prevState, nextState) => {
9
+ return nextState;
10
+ });
11
+
12
+ exports.MetricsStore = MetricsStore;
13
+ exports.setInstantMetrics = setInstantMetrics;
@@ -0,0 +1,22 @@
1
+ import { DEFAULT_BUCKETS } from '../constants.es.js';
2
+
3
+ const commandLineMetrics = (metrics) => {
4
+ const metricsInstance = metrics.histogram({
5
+ name: `command_line_runner_execution_time`,
6
+ help: 'Command line processing duration',
7
+ labelNames: ['line'],
8
+ buckets: DEFAULT_BUCKETS,
9
+ });
10
+ return (di, type, status, timingInfo) => {
11
+ for (const line in timingInfo) {
12
+ const info = timingInfo[line];
13
+ if (info.end) {
14
+ const durationInMs = info.end - info.start;
15
+ const durationInSec = durationInMs / 1000;
16
+ metricsInstance.observe({ line }, durationInSec);
17
+ }
18
+ }
19
+ };
20
+ };
21
+
22
+ export { commandLineMetrics };
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var constants = require('../constants.js');
6
+
7
+ const commandLineMetrics = (metrics) => {
8
+ const metricsInstance = metrics.histogram({
9
+ name: `command_line_runner_execution_time`,
10
+ help: 'Command line processing duration',
11
+ labelNames: ['line'],
12
+ buckets: constants.DEFAULT_BUCKETS,
13
+ });
14
+ return (di, type, status, timingInfo) => {
15
+ for (const line in timingInfo) {
16
+ const info = timingInfo[line];
17
+ if (info.end) {
18
+ const durationInMs = info.end - info.start;
19
+ const durationInSec = durationInMs / 1000;
20
+ metricsInstance.observe({ line }, durationInSec);
21
+ }
22
+ }
23
+ };
24
+ };
25
+
26
+ exports.commandLineMetrics = commandLineMetrics;
@@ -0,0 +1,23 @@
1
+ const NODEJS_EVENTLOOP_LAG = 'nodejs_eventloop_setinterval_lag_seconds';
2
+ function startEventLoopLagMeasure(histogram) {
3
+ let start = process.hrtime();
4
+ const interval = 100;
5
+ setInterval(() => {
6
+ const delta = process.hrtime(start);
7
+ const nanosec = delta[0] * 1e9 + delta[1];
8
+ const ms = nanosec / 1e6;
9
+ const lag = ms - interval;
10
+ histogram.observe(lag / 1e3);
11
+ start = process.hrtime();
12
+ }, interval).unref();
13
+ }
14
+ const eventLoopMetrics = (metrics) => {
15
+ const histogram = metrics.histogram({
16
+ name: NODEJS_EVENTLOOP_LAG,
17
+ help: 'Lag of event loop in seconds (setInterval based).',
18
+ buckets: [0.02, 0.1, 0.2, 0.5, 1, 3, 5, 7.5, 10],
19
+ });
20
+ startEventLoopLagMeasure(histogram);
21
+ };
22
+
23
+ export { eventLoopMetrics };
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const NODEJS_EVENTLOOP_LAG = 'nodejs_eventloop_setinterval_lag_seconds';
6
+ function startEventLoopLagMeasure(histogram) {
7
+ let start = process.hrtime();
8
+ const interval = 100;
9
+ setInterval(() => {
10
+ const delta = process.hrtime(start);
11
+ const nanosec = delta[0] * 1e9 + delta[1];
12
+ const ms = nanosec / 1e6;
13
+ const lag = ms - interval;
14
+ histogram.observe(lag / 1e3);
15
+ start = process.hrtime();
16
+ }, interval).unref();
17
+ }
18
+ const eventLoopMetrics = (metrics) => {
19
+ const histogram = metrics.histogram({
20
+ name: NODEJS_EVENTLOOP_LAG,
21
+ help: 'Lag of event loop in seconds (setInterval based).',
22
+ buckets: [0.02, 0.1, 0.2, 0.5, 1, 3, 5, 7.5, 10],
23
+ });
24
+ startEventLoopLagMeasure(histogram);
25
+ };
26
+
27
+ exports.eventLoopMetrics = eventLoopMetrics;