@tramvai/module-metrics 7.21.1 → 7.26.9
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/lib/metrics/papi.d.ts +14 -0
- package/lib/metrics/papi.es.js +33 -0
- package/lib/metrics/papi.js +41 -0
- package/lib/request/createRequestWithMetrics.d.ts +2 -6
- package/lib/request/createRequestWithMetrics.es.js +85 -40
- package/lib/request/createRequestWithMetrics.js +90 -40
- package/lib/server.es.js +11 -1
- package/lib/server.js +10 -0
- package/package.json +11 -11
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { METRICS_MODULE_TOKEN } from '@tramvai/tokens-metrics';
|
|
2
|
+
import type { FastifyInstance } from 'fastify';
|
|
3
|
+
declare const METRICS_PAPI_TIMER = "_papi_metrics_timer";
|
|
4
|
+
declare module 'fastify' {
|
|
5
|
+
interface FastifyRequest {
|
|
6
|
+
[METRICS_PAPI_TIMER]: (labels?: Record<string, any>) => void;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export interface AddPapiMetricsOptions {
|
|
10
|
+
metrics: typeof METRICS_MODULE_TOKEN;
|
|
11
|
+
}
|
|
12
|
+
export declare const papiMetrics: (fastify: FastifyInstance, { metrics }: AddPapiMetricsOptions) => Promise<void>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=papi.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import noop from '@tinkoff/utils/function/noop';
|
|
2
|
+
|
|
3
|
+
const METRICS_PAPI_TIMER = '_papi_metrics_timer';
|
|
4
|
+
const LABEL_NAMES = ['method', 'path', 'status'];
|
|
5
|
+
const DEFAULT_BUCKETS = [0.01, 0.05, 0.1, 0.3, 0.4, 0.5, 1, 2.5, 5, 10, 20, 40, 60];
|
|
6
|
+
const papiMetrics = async (fastify, { metrics }) => {
|
|
7
|
+
const requestTotal = metrics.counter({
|
|
8
|
+
name: 'papi_requests_total',
|
|
9
|
+
help: 'Total PAPI requests processed',
|
|
10
|
+
labelNames: LABEL_NAMES,
|
|
11
|
+
});
|
|
12
|
+
const executionTime = metrics.histogram({
|
|
13
|
+
name: 'papi_requests_execution_time',
|
|
14
|
+
help: 'PAPI requests processing duration',
|
|
15
|
+
buckets: DEFAULT_BUCKETS,
|
|
16
|
+
labelNames: LABEL_NAMES,
|
|
17
|
+
});
|
|
18
|
+
fastify.decorateRequest(METRICS_PAPI_TIMER, noop);
|
|
19
|
+
fastify.addHook('onRequest', async (req) => {
|
|
20
|
+
req[METRICS_PAPI_TIMER] = executionTime.startTimer();
|
|
21
|
+
});
|
|
22
|
+
fastify.addHook('onResponse', async (req, res) => {
|
|
23
|
+
const labels = {
|
|
24
|
+
method: req.method,
|
|
25
|
+
path: req.routeOptions.url ?? req.url,
|
|
26
|
+
status: res.statusCode,
|
|
27
|
+
};
|
|
28
|
+
requestTotal.inc(labels);
|
|
29
|
+
req[METRICS_PAPI_TIMER](labels);
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export { papiMetrics };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var noop = require('@tinkoff/utils/function/noop');
|
|
6
|
+
|
|
7
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
|
+
|
|
9
|
+
var noop__default = /*#__PURE__*/_interopDefaultLegacy(noop);
|
|
10
|
+
|
|
11
|
+
const METRICS_PAPI_TIMER = '_papi_metrics_timer';
|
|
12
|
+
const LABEL_NAMES = ['method', 'path', 'status'];
|
|
13
|
+
const DEFAULT_BUCKETS = [0.01, 0.05, 0.1, 0.3, 0.4, 0.5, 1, 2.5, 5, 10, 20, 40, 60];
|
|
14
|
+
const papiMetrics = async (fastify, { metrics }) => {
|
|
15
|
+
const requestTotal = metrics.counter({
|
|
16
|
+
name: 'papi_requests_total',
|
|
17
|
+
help: 'Total PAPI requests processed',
|
|
18
|
+
labelNames: LABEL_NAMES,
|
|
19
|
+
});
|
|
20
|
+
const executionTime = metrics.histogram({
|
|
21
|
+
name: 'papi_requests_execution_time',
|
|
22
|
+
help: 'PAPI requests processing duration',
|
|
23
|
+
buckets: DEFAULT_BUCKETS,
|
|
24
|
+
labelNames: LABEL_NAMES,
|
|
25
|
+
});
|
|
26
|
+
fastify.decorateRequest(METRICS_PAPI_TIMER, noop__default["default"]);
|
|
27
|
+
fastify.addHook('onRequest', async (req) => {
|
|
28
|
+
req[METRICS_PAPI_TIMER] = executionTime.startTimer();
|
|
29
|
+
});
|
|
30
|
+
fastify.addHook('onResponse', async (req, res) => {
|
|
31
|
+
const labels = {
|
|
32
|
+
method: req.method,
|
|
33
|
+
path: req.routeOptions.url ?? req.url,
|
|
34
|
+
status: res.statusCode,
|
|
35
|
+
};
|
|
36
|
+
requestTotal.inc(labels);
|
|
37
|
+
req[METRICS_PAPI_TIMER](labels);
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
exports.papiMetrics = papiMetrics;
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import type { Args, CreateRequestWithMetrics } from './types';
|
|
2
2
|
export declare const getUrlAndOptions: (args: Args) => any[];
|
|
3
3
|
export declare const createRequestWithMetrics: CreateRequestWithMetrics;
|
|
4
|
-
export declare function initConnectionResolveMetrics({ metricsInstances
|
|
5
|
-
metricsInstances:
|
|
6
|
-
dnsResolveDuration: any;
|
|
7
|
-
tcpConnectDuration: any;
|
|
8
|
-
tlsHandshakeDuration: any;
|
|
9
|
-
};
|
|
4
|
+
export declare function initConnectionResolveMetrics({ metricsInstances }: {
|
|
5
|
+
metricsInstances: any;
|
|
10
6
|
}): void;
|
|
11
7
|
export declare const addMetricsForFetch: ({ metricsInstances: { requestsTotal, requestsErrors, requestsDuration }, getServiceName, }: {
|
|
12
8
|
metricsInstances: {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { format } from '@tinkoff/url';
|
|
2
1
|
import { subscribe } from 'diagnostics_channel';
|
|
2
|
+
import net from 'node:net';
|
|
3
|
+
import tls from 'node:tls';
|
|
3
4
|
import { UndiciError } from 'undici/lib/core/errors';
|
|
4
|
-
import {
|
|
5
|
+
import { format } from '@tinkoff/url';
|
|
5
6
|
|
|
6
7
|
// https://nodejs.org/api/errors.html#nodejs-error-codes - Common system errors possible for net/http/dns
|
|
7
8
|
const POSSIBLE_ERRORS = [
|
|
@@ -12,6 +13,23 @@ const POSSIBLE_ERRORS = [
|
|
|
12
13
|
'EPIPE',
|
|
13
14
|
'ETIMEDOUT',
|
|
14
15
|
];
|
|
16
|
+
const kMetricsAttached = Symbol('metricsAttached');
|
|
17
|
+
const UNKNOWN_HOST = 'unknown';
|
|
18
|
+
const isCorrectEmitNet = Number(process.versions.node.split('.')[0]) > 20;
|
|
19
|
+
const removeDefaultPorts = (urlWithPort) => {
|
|
20
|
+
try {
|
|
21
|
+
const url = new URL(urlWithPort.toString());
|
|
22
|
+
const currentPort = url.port;
|
|
23
|
+
if (currentPort === '80' || currentPort === '443') {
|
|
24
|
+
url.port = '';
|
|
25
|
+
}
|
|
26
|
+
return url.origin;
|
|
27
|
+
}
|
|
28
|
+
catch (_err) { }
|
|
29
|
+
return urlWithPort;
|
|
30
|
+
};
|
|
31
|
+
const originalNetConnect = net.Socket.prototype.connect;
|
|
32
|
+
const originalTlsConnect = tls.connect;
|
|
15
33
|
// eslint-disable-next-line max-statements
|
|
16
34
|
const getUrlAndOptions = (args) => {
|
|
17
35
|
let url;
|
|
@@ -90,55 +108,82 @@ const createRequestWithMetrics = ({ metricsInstances: { requestsTotal, requestsE
|
|
|
90
108
|
return req;
|
|
91
109
|
};
|
|
92
110
|
};
|
|
93
|
-
function initConnectionResolveMetrics({ metricsInstances
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
secureConnectEnd: 0,
|
|
100
|
-
host: 'unknown',
|
|
101
|
-
};
|
|
102
|
-
const protocol = socket instanceof TLSSocket ? 'https' : 'http';
|
|
103
|
-
socket.once('lookup', (_err, _address, _family, host) => {
|
|
104
|
-
socketInfo.lookupEnd = Date.now();
|
|
105
|
-
dnsResolveDuration.observe({ service: host }, getDuration(socketInfo.lookupEnd, socketInfo.start));
|
|
106
|
-
});
|
|
107
|
-
socket.on('connect', () => {
|
|
108
|
-
socketInfo.connectEnd = Date.now();
|
|
109
|
-
let service;
|
|
110
|
-
if (protocol === 'http') {
|
|
111
|
-
// _host is internal field - https://github.com/nodejs/node/blob/main/lib/net.js#L1383
|
|
112
|
-
const { remotePort: port, _host: host } = socket;
|
|
113
|
-
service = `${protocol}://${host}:${port}`;
|
|
114
|
-
socketInfo.host = host;
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
// connect-options also internal - https://github.com/nodejs/node/blob/main/lib/internal/tls/wrap.js#L1749
|
|
118
|
-
const connectOptionsSymbol = Object.getOwnPropertySymbols(socket).find((smb) => smb.toString() === 'Symbol(connect-options)');
|
|
119
|
-
const connectOptions = socket[connectOptionsSymbol];
|
|
120
|
-
const { port, host } = connectOptions;
|
|
121
|
-
service = `${protocol}://${host}:${port}`;
|
|
122
|
-
socketInfo.host = host;
|
|
123
|
-
}
|
|
124
|
-
tcpConnectDuration.observe({ service }, getDuration(socketInfo.connectEnd, socketInfo.lookupEnd));
|
|
125
|
-
});
|
|
126
|
-
socket.on('secureConnect', () => {
|
|
127
|
-
socketInfo.secureConnectEnd = Date.now();
|
|
128
|
-
tlsHandshakeDuration.observe({ service: socketInfo.host }, getDuration(socketInfo.secureConnectEnd, socketInfo.connectEnd));
|
|
111
|
+
function initConnectionResolveMetrics({ metricsInstances }) {
|
|
112
|
+
if (isCorrectEmitNet) {
|
|
113
|
+
subscribe('net.client.socket', ({ socket }) => {
|
|
114
|
+
instrumentSocket(socket, {
|
|
115
|
+
metricsInstances,
|
|
116
|
+
});
|
|
129
117
|
});
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
net.Socket.prototype.connect = function patchedNetConnect(...args) {
|
|
121
|
+
const socket = originalNetConnect.apply(this, args);
|
|
122
|
+
instrumentSocket(socket, {
|
|
123
|
+
metricsInstances,
|
|
124
|
+
});
|
|
125
|
+
return socket;
|
|
126
|
+
};
|
|
127
|
+
tls.connect = function patchedTlsConnect(...args) {
|
|
128
|
+
const socket = originalTlsConnect.apply(this, args);
|
|
129
|
+
instrumentSocket(socket, {
|
|
130
|
+
metricsInstances,
|
|
131
|
+
});
|
|
132
|
+
return socket;
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function instrumentSocket(socket, { metricsInstances: { dnsResolveDuration, tcpConnectDuration, tlsHandshakeDuration } }) {
|
|
137
|
+
// ignore reused sockets
|
|
138
|
+
if (socket[kMetricsAttached]) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
socket[kMetricsAttached] = true;
|
|
142
|
+
const socketInfo = {
|
|
143
|
+
start: Date.now(),
|
|
144
|
+
lookupEnd: 0,
|
|
145
|
+
connectEnd: 0,
|
|
146
|
+
secureConnectEnd: 0,
|
|
147
|
+
host: UNKNOWN_HOST,
|
|
148
|
+
};
|
|
149
|
+
const protocol = socket instanceof tls.TLSSocket ? 'https' : 'http';
|
|
150
|
+
socket.once('lookup', (_err, _address, _family, host) => {
|
|
151
|
+
socketInfo.lookupEnd = Date.now();
|
|
152
|
+
socketInfo.host = host;
|
|
153
|
+
dnsResolveDuration.observe({ service: host }, getDuration(socketInfo.lookupEnd, socketInfo.start));
|
|
154
|
+
});
|
|
155
|
+
socket.once('connect', () => {
|
|
156
|
+
socketInfo.connectEnd = Date.now();
|
|
157
|
+
if (protocol === 'http') {
|
|
158
|
+
// _host is internal field - https://github.com/nodejs/node/blob/main/lib/net.js#L1383
|
|
159
|
+
const { _host: host } = socket;
|
|
160
|
+
socketInfo.host = `http://${host ?? socketInfo.host}`;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
// connect-options also internal - https://github.com/nodejs/node/blob/main/lib/internal/tls/wrap.js#L1749
|
|
164
|
+
const connectOptionsSymbol = Object.getOwnPropertySymbols(socket).find((smb) => smb.toString() === 'Symbol(connect-options)');
|
|
165
|
+
const connectOptions = socket[connectOptionsSymbol];
|
|
166
|
+
const { servername } = connectOptions;
|
|
167
|
+
socketInfo.host = `https://${servername ?? socketInfo.host}`;
|
|
168
|
+
}
|
|
169
|
+
tcpConnectDuration.observe({ service: socketInfo.host }, getDuration(socketInfo.connectEnd, socketInfo.lookupEnd));
|
|
170
|
+
});
|
|
171
|
+
socket.once('secureConnect', () => {
|
|
172
|
+
socketInfo.secureConnectEnd = Date.now();
|
|
173
|
+
tlsHandshakeDuration.observe({ service: socketInfo.host }, getDuration(socketInfo.secureConnectEnd, socketInfo.connectEnd));
|
|
130
174
|
});
|
|
131
175
|
}
|
|
132
176
|
const requestMetricsSymbol = Symbol('request-metrics');
|
|
133
177
|
const addMetricsForFetch = ({ metricsInstances: { requestsTotal, requestsErrors, requestsDuration }, getServiceName, }) => {
|
|
134
178
|
subscribe('undici:request:create', ({ request }) => {
|
|
135
179
|
const { method, origin, path } = request;
|
|
136
|
-
const
|
|
180
|
+
const host = removeDefaultPorts(origin);
|
|
181
|
+
const url = `${host}${path}`;
|
|
137
182
|
const serviceName = getServiceName(url, request);
|
|
138
183
|
const timerDone = requestsDuration.startTimer();
|
|
139
184
|
const labelsValues = {
|
|
140
185
|
method: method ?? 'unknown',
|
|
141
|
-
service: serviceName ||
|
|
186
|
+
service: serviceName || host || 'unknown',
|
|
142
187
|
status: 'unknown',
|
|
143
188
|
};
|
|
144
189
|
request[requestMetricsSymbol] = {
|
|
@@ -2,10 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var url = require('@tinkoff/url');
|
|
6
5
|
var diagnostics_channel = require('diagnostics_channel');
|
|
6
|
+
var net = require('node:net');
|
|
7
|
+
var tls = require('node:tls');
|
|
7
8
|
var errors = require('undici/lib/core/errors');
|
|
8
|
-
var
|
|
9
|
+
var url = require('@tinkoff/url');
|
|
10
|
+
|
|
11
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
12
|
+
|
|
13
|
+
var net__default = /*#__PURE__*/_interopDefaultLegacy(net);
|
|
14
|
+
var tls__default = /*#__PURE__*/_interopDefaultLegacy(tls);
|
|
9
15
|
|
|
10
16
|
// https://nodejs.org/api/errors.html#nodejs-error-codes - Common system errors possible for net/http/dns
|
|
11
17
|
const POSSIBLE_ERRORS = [
|
|
@@ -16,6 +22,23 @@ const POSSIBLE_ERRORS = [
|
|
|
16
22
|
'EPIPE',
|
|
17
23
|
'ETIMEDOUT',
|
|
18
24
|
];
|
|
25
|
+
const kMetricsAttached = Symbol('metricsAttached');
|
|
26
|
+
const UNKNOWN_HOST = 'unknown';
|
|
27
|
+
const isCorrectEmitNet = Number(process.versions.node.split('.')[0]) > 20;
|
|
28
|
+
const removeDefaultPorts = (urlWithPort) => {
|
|
29
|
+
try {
|
|
30
|
+
const url = new URL(urlWithPort.toString());
|
|
31
|
+
const currentPort = url.port;
|
|
32
|
+
if (currentPort === '80' || currentPort === '443') {
|
|
33
|
+
url.port = '';
|
|
34
|
+
}
|
|
35
|
+
return url.origin;
|
|
36
|
+
}
|
|
37
|
+
catch (_err) { }
|
|
38
|
+
return urlWithPort;
|
|
39
|
+
};
|
|
40
|
+
const originalNetConnect = net__default["default"].Socket.prototype.connect;
|
|
41
|
+
const originalTlsConnect = tls__default["default"].connect;
|
|
19
42
|
// eslint-disable-next-line max-statements
|
|
20
43
|
const getUrlAndOptions = (args) => {
|
|
21
44
|
let url$1;
|
|
@@ -94,55 +117,82 @@ const createRequestWithMetrics = ({ metricsInstances: { requestsTotal, requestsE
|
|
|
94
117
|
return req;
|
|
95
118
|
};
|
|
96
119
|
};
|
|
97
|
-
function initConnectionResolveMetrics({ metricsInstances
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
secureConnectEnd: 0,
|
|
104
|
-
host: 'unknown',
|
|
105
|
-
};
|
|
106
|
-
const protocol = socket instanceof tls.TLSSocket ? 'https' : 'http';
|
|
107
|
-
socket.once('lookup', (_err, _address, _family, host) => {
|
|
108
|
-
socketInfo.lookupEnd = Date.now();
|
|
109
|
-
dnsResolveDuration.observe({ service: host }, getDuration(socketInfo.lookupEnd, socketInfo.start));
|
|
110
|
-
});
|
|
111
|
-
socket.on('connect', () => {
|
|
112
|
-
socketInfo.connectEnd = Date.now();
|
|
113
|
-
let service;
|
|
114
|
-
if (protocol === 'http') {
|
|
115
|
-
// _host is internal field - https://github.com/nodejs/node/blob/main/lib/net.js#L1383
|
|
116
|
-
const { remotePort: port, _host: host } = socket;
|
|
117
|
-
service = `${protocol}://${host}:${port}`;
|
|
118
|
-
socketInfo.host = host;
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
// connect-options also internal - https://github.com/nodejs/node/blob/main/lib/internal/tls/wrap.js#L1749
|
|
122
|
-
const connectOptionsSymbol = Object.getOwnPropertySymbols(socket).find((smb) => smb.toString() === 'Symbol(connect-options)');
|
|
123
|
-
const connectOptions = socket[connectOptionsSymbol];
|
|
124
|
-
const { port, host } = connectOptions;
|
|
125
|
-
service = `${protocol}://${host}:${port}`;
|
|
126
|
-
socketInfo.host = host;
|
|
127
|
-
}
|
|
128
|
-
tcpConnectDuration.observe({ service }, getDuration(socketInfo.connectEnd, socketInfo.lookupEnd));
|
|
129
|
-
});
|
|
130
|
-
socket.on('secureConnect', () => {
|
|
131
|
-
socketInfo.secureConnectEnd = Date.now();
|
|
132
|
-
tlsHandshakeDuration.observe({ service: socketInfo.host }, getDuration(socketInfo.secureConnectEnd, socketInfo.connectEnd));
|
|
120
|
+
function initConnectionResolveMetrics({ metricsInstances }) {
|
|
121
|
+
if (isCorrectEmitNet) {
|
|
122
|
+
diagnostics_channel.subscribe('net.client.socket', ({ socket }) => {
|
|
123
|
+
instrumentSocket(socket, {
|
|
124
|
+
metricsInstances,
|
|
125
|
+
});
|
|
133
126
|
});
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
net__default["default"].Socket.prototype.connect = function patchedNetConnect(...args) {
|
|
130
|
+
const socket = originalNetConnect.apply(this, args);
|
|
131
|
+
instrumentSocket(socket, {
|
|
132
|
+
metricsInstances,
|
|
133
|
+
});
|
|
134
|
+
return socket;
|
|
135
|
+
};
|
|
136
|
+
tls__default["default"].connect = function patchedTlsConnect(...args) {
|
|
137
|
+
const socket = originalTlsConnect.apply(this, args);
|
|
138
|
+
instrumentSocket(socket, {
|
|
139
|
+
metricsInstances,
|
|
140
|
+
});
|
|
141
|
+
return socket;
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function instrumentSocket(socket, { metricsInstances: { dnsResolveDuration, tcpConnectDuration, tlsHandshakeDuration } }) {
|
|
146
|
+
// ignore reused sockets
|
|
147
|
+
if (socket[kMetricsAttached]) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
socket[kMetricsAttached] = true;
|
|
151
|
+
const socketInfo = {
|
|
152
|
+
start: Date.now(),
|
|
153
|
+
lookupEnd: 0,
|
|
154
|
+
connectEnd: 0,
|
|
155
|
+
secureConnectEnd: 0,
|
|
156
|
+
host: UNKNOWN_HOST,
|
|
157
|
+
};
|
|
158
|
+
const protocol = socket instanceof tls__default["default"].TLSSocket ? 'https' : 'http';
|
|
159
|
+
socket.once('lookup', (_err, _address, _family, host) => {
|
|
160
|
+
socketInfo.lookupEnd = Date.now();
|
|
161
|
+
socketInfo.host = host;
|
|
162
|
+
dnsResolveDuration.observe({ service: host }, getDuration(socketInfo.lookupEnd, socketInfo.start));
|
|
163
|
+
});
|
|
164
|
+
socket.once('connect', () => {
|
|
165
|
+
socketInfo.connectEnd = Date.now();
|
|
166
|
+
if (protocol === 'http') {
|
|
167
|
+
// _host is internal field - https://github.com/nodejs/node/blob/main/lib/net.js#L1383
|
|
168
|
+
const { _host: host } = socket;
|
|
169
|
+
socketInfo.host = `http://${host ?? socketInfo.host}`;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
// connect-options also internal - https://github.com/nodejs/node/blob/main/lib/internal/tls/wrap.js#L1749
|
|
173
|
+
const connectOptionsSymbol = Object.getOwnPropertySymbols(socket).find((smb) => smb.toString() === 'Symbol(connect-options)');
|
|
174
|
+
const connectOptions = socket[connectOptionsSymbol];
|
|
175
|
+
const { servername } = connectOptions;
|
|
176
|
+
socketInfo.host = `https://${servername ?? socketInfo.host}`;
|
|
177
|
+
}
|
|
178
|
+
tcpConnectDuration.observe({ service: socketInfo.host }, getDuration(socketInfo.connectEnd, socketInfo.lookupEnd));
|
|
179
|
+
});
|
|
180
|
+
socket.once('secureConnect', () => {
|
|
181
|
+
socketInfo.secureConnectEnd = Date.now();
|
|
182
|
+
tlsHandshakeDuration.observe({ service: socketInfo.host }, getDuration(socketInfo.secureConnectEnd, socketInfo.connectEnd));
|
|
134
183
|
});
|
|
135
184
|
}
|
|
136
185
|
const requestMetricsSymbol = Symbol('request-metrics');
|
|
137
186
|
const addMetricsForFetch = ({ metricsInstances: { requestsTotal, requestsErrors, requestsDuration }, getServiceName, }) => {
|
|
138
187
|
diagnostics_channel.subscribe('undici:request:create', ({ request }) => {
|
|
139
188
|
const { method, origin, path } = request;
|
|
140
|
-
const
|
|
189
|
+
const host = removeDefaultPorts(origin);
|
|
190
|
+
const url = `${host}${path}`;
|
|
141
191
|
const serviceName = getServiceName(url, request);
|
|
142
192
|
const timerDone = requestsDuration.startTimer();
|
|
143
193
|
const labelsValues = {
|
|
144
194
|
method: method ?? 'unknown',
|
|
145
|
-
service: serviceName ||
|
|
195
|
+
service: serviceName || host || 'unknown',
|
|
146
196
|
status: 'unknown',
|
|
147
197
|
};
|
|
148
198
|
request[requestMetricsSymbol] = {
|
package/lib/server.es.js
CHANGED
|
@@ -2,7 +2,7 @@ import { __decorate } from 'tslib';
|
|
|
2
2
|
import { Module, provide, Scope, commandLineListTokens } from '@tramvai/core';
|
|
3
3
|
import { COMMAND_LINE_EXECUTION_END_TOKEN } from '@tramvai/tokens-core-private';
|
|
4
4
|
import { UTILITY_SERVER_PATHS } from '@tramvai/tokens-server';
|
|
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';
|
|
5
|
+
import { WEB_FASTIFY_APP_BEFORE_INIT_TOKEN, UTILITY_WEB_FASTIFY_APP_TOKEN, WEB_FASTIFY_APP_METRICS_TOKEN, WEB_FASTIFY_APP_TOKEN, PAPI_METRICS_TOKEN } from '@tramvai/tokens-server-private';
|
|
6
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';
|
|
@@ -12,6 +12,7 @@ import { RequestModule } from './request/index.es.js';
|
|
|
12
12
|
import { InstantMetricsModule } from './instantMetrics/server.es.js';
|
|
13
13
|
import { eventLoopMetrics } from './metrics/eventLoop.es.js';
|
|
14
14
|
import { commandLineMetrics } from './metrics/commandLine.es.js';
|
|
15
|
+
import { papiMetrics } from './metrics/papi.es.js';
|
|
15
16
|
import { METRICS_DEFAULT_REGISTRY } from './tokens.es.js';
|
|
16
17
|
export { METRICS_DEFAULT_REGISTRY } from './tokens.es.js';
|
|
17
18
|
export { getUrlAndOptions } from './request/createRequestWithMetrics.es.js';
|
|
@@ -134,6 +135,15 @@ MetricsModule = __decorate([
|
|
|
134
135
|
metrics: METRICS_MODULE_TOKEN,
|
|
135
136
|
},
|
|
136
137
|
}),
|
|
138
|
+
provide({
|
|
139
|
+
provide: PAPI_METRICS_TOKEN,
|
|
140
|
+
useFactory: ({ metrics }) => {
|
|
141
|
+
return (app) => papiMetrics(app, { metrics });
|
|
142
|
+
},
|
|
143
|
+
deps: {
|
|
144
|
+
metrics: METRICS_MODULE_TOKEN,
|
|
145
|
+
},
|
|
146
|
+
}),
|
|
137
147
|
],
|
|
138
148
|
})
|
|
139
149
|
], MetricsModule);
|
package/lib/server.js
CHANGED
|
@@ -15,6 +15,7 @@ var index = require('./request/index.js');
|
|
|
15
15
|
var server = require('./instantMetrics/server.js');
|
|
16
16
|
var eventLoop = require('./metrics/eventLoop.js');
|
|
17
17
|
var commandLine = require('./metrics/commandLine.js');
|
|
18
|
+
var papi = require('./metrics/papi.js');
|
|
18
19
|
var tokens = require('./tokens.js');
|
|
19
20
|
var createRequestWithMetrics = require('./request/createRequestWithMetrics.js');
|
|
20
21
|
var MetricsServicesRegistry = require('./request/MetricsServicesRegistry.js');
|
|
@@ -140,6 +141,15 @@ exports.MetricsModule = tslib.__decorate([
|
|
|
140
141
|
metrics: tokensMetrics.METRICS_MODULE_TOKEN,
|
|
141
142
|
},
|
|
142
143
|
}),
|
|
144
|
+
core.provide({
|
|
145
|
+
provide: tokensServerPrivate.PAPI_METRICS_TOKEN,
|
|
146
|
+
useFactory: ({ metrics }) => {
|
|
147
|
+
return (app) => papi.papiMetrics(app, { metrics });
|
|
148
|
+
},
|
|
149
|
+
deps: {
|
|
150
|
+
metrics: tokensMetrics.METRICS_MODULE_TOKEN,
|
|
151
|
+
},
|
|
152
|
+
}),
|
|
143
153
|
],
|
|
144
154
|
})
|
|
145
155
|
], exports.MetricsModule);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tramvai/module-metrics",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.26.9",
|
|
4
4
|
"description": "",
|
|
5
5
|
"browser": "lib/browser.js",
|
|
6
6
|
"main": "lib/server.js",
|
|
@@ -25,16 +25,16 @@
|
|
|
25
25
|
"@tinkoff/monkeypatch": "7.0.1",
|
|
26
26
|
"@tinkoff/url": "0.13.1",
|
|
27
27
|
"@tinkoff/utils": "^2.1.2",
|
|
28
|
-
"@tramvai/core": "7.
|
|
29
|
-
"@tramvai/papi": "7.
|
|
30
|
-
"@tramvai/state": "7.
|
|
31
|
-
"@tramvai/tokens-common": "7.
|
|
32
|
-
"@tramvai/tokens-core-private": "7.
|
|
33
|
-
"@tramvai/tokens-http-client": "7.
|
|
34
|
-
"@tramvai/tokens-metrics": "7.
|
|
35
|
-
"@tramvai/tokens-router": "7.
|
|
36
|
-
"@tramvai/tokens-server": "7.
|
|
37
|
-
"@tramvai/tokens-server-private": "7.
|
|
28
|
+
"@tramvai/core": "7.26.9",
|
|
29
|
+
"@tramvai/papi": "7.26.9",
|
|
30
|
+
"@tramvai/state": "7.26.9",
|
|
31
|
+
"@tramvai/tokens-common": "7.26.9",
|
|
32
|
+
"@tramvai/tokens-core-private": "7.26.9",
|
|
33
|
+
"@tramvai/tokens-http-client": "7.26.9",
|
|
34
|
+
"@tramvai/tokens-metrics": "7.26.9",
|
|
35
|
+
"@tramvai/tokens-router": "7.26.9",
|
|
36
|
+
"@tramvai/tokens-server": "7.26.9",
|
|
37
|
+
"@tramvai/tokens-server-private": "7.26.9",
|
|
38
38
|
"prom-client": "^14.2.0",
|
|
39
39
|
"undici": "^7.24.4"
|
|
40
40
|
},
|