@opentelemetry/instrumentation-http 0.53.0 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -6
- package/build/src/http.d.ts +10 -4
- package/build/src/http.js +163 -66
- package/build/src/http.js.map +1 -1
- package/build/src/index.d.ts +1 -1
- package/build/src/index.js +1 -2
- package/build/src/index.js.map +1 -1
- package/build/src/types.d.ts +17 -13
- package/build/src/types.js.map +1 -1
- package/build/src/utils.d.ts +39 -35
- package/build/src/utils.js +287 -79
- package/build/src/utils.js.map +1 -1
- package/build/src/version.d.ts +1 -1
- package/build/src/version.js +1 -1
- package/build/src/version.js.map +1 -1
- package/package.json +12 -13
package/build/src/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.headerCapture = exports.getIncomingRequestMetricAttributesOnResponse = exports.getIncomingRequestAttributesOnResponse = exports.getIncomingRequestMetricAttributes = exports.getIncomingRequestAttributes = exports.getOutgoingRequestMetricAttributesOnResponse = exports.getOutgoingRequestAttributesOnResponse = exports.setAttributesFromHttpKind = exports.getOutgoingRequestMetricAttributes = exports.getOutgoingRequestAttributes = exports.extractHostnameAndPort = exports.isValidOptionsType = exports.getRequestInfo = exports.isCompressed = exports.setResponseContentLengthAttribute = exports.setRequestContentLengthAttribute = exports.setSpanWithError = exports.
|
|
3
|
+
exports.headerCapture = exports.getIncomingStableRequestMetricAttributesOnResponse = exports.getIncomingRequestMetricAttributesOnResponse = exports.getIncomingRequestAttributesOnResponse = exports.getIncomingRequestMetricAttributes = exports.getIncomingRequestAttributes = exports.getRemoteClientAddress = exports.getOutgoingRequestMetricAttributesOnResponse = exports.getOutgoingRequestAttributesOnResponse = exports.setAttributesFromHttpKind = exports.getOutgoingRequestMetricAttributes = exports.getOutgoingRequestAttributes = exports.extractHostnameAndPort = exports.isValidOptionsType = exports.getRequestInfo = exports.isCompressed = exports.setResponseContentLengthAttribute = exports.setRequestContentLengthAttribute = exports.setSpanWithError = exports.satisfiesPattern = exports.parseResponseStatus = exports.getAbsoluteUrl = void 0;
|
|
4
4
|
/*
|
|
5
5
|
* Copyright The OpenTelemetry Authors
|
|
6
6
|
*
|
|
@@ -21,6 +21,7 @@ const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
|
|
|
21
21
|
const core_1 = require("@opentelemetry/core");
|
|
22
22
|
const url = require("url");
|
|
23
23
|
const AttributeNames_1 = require("./enums/AttributeNames");
|
|
24
|
+
const forwardedParse = require("forwarded-parse");
|
|
24
25
|
/**
|
|
25
26
|
* Get an absolute url
|
|
26
27
|
*/
|
|
@@ -75,44 +76,22 @@ const satisfiesPattern = (constant, pattern) => {
|
|
|
75
76
|
}
|
|
76
77
|
};
|
|
77
78
|
exports.satisfiesPattern = satisfiesPattern;
|
|
78
|
-
/**
|
|
79
|
-
* Check whether the given request is ignored by configuration
|
|
80
|
-
* It will not re-throw exceptions from `list` provided by the client
|
|
81
|
-
* @param constant e.g URL of request
|
|
82
|
-
* @param [list] List of ignore patterns
|
|
83
|
-
* @param [onException] callback for doing something when an exception has
|
|
84
|
-
* occurred
|
|
85
|
-
*/
|
|
86
|
-
const isIgnored = (constant, list, onException) => {
|
|
87
|
-
if (!list) {
|
|
88
|
-
// No ignored urls - trace everything
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
// Try/catch outside the loop for failing fast
|
|
92
|
-
try {
|
|
93
|
-
for (const pattern of list) {
|
|
94
|
-
if ((0, exports.satisfiesPattern)(constant, pattern)) {
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
catch (e) {
|
|
100
|
-
if (onException) {
|
|
101
|
-
onException(e);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return false;
|
|
105
|
-
};
|
|
106
|
-
exports.isIgnored = isIgnored;
|
|
107
79
|
/**
|
|
108
80
|
* Sets the span with the error passed in params
|
|
109
81
|
* @param {Span} span the span that need to be set
|
|
110
82
|
* @param {Error} error error that will be set to span
|
|
83
|
+
* @param {SemconvStability} semconvStability determines which semconv version to use
|
|
111
84
|
*/
|
|
112
|
-
const setSpanWithError = (span, error) => {
|
|
85
|
+
const setSpanWithError = (span, error, semconvStability) => {
|
|
113
86
|
const message = error.message;
|
|
114
|
-
|
|
115
|
-
|
|
87
|
+
if ((semconvStability & 2 /* OLD */) === 2 /* OLD */) {
|
|
88
|
+
span.setAttribute(AttributeNames_1.AttributeNames.HTTP_ERROR_NAME, error.name);
|
|
89
|
+
span.setAttribute(AttributeNames_1.AttributeNames.HTTP_ERROR_MESSAGE, message);
|
|
90
|
+
}
|
|
91
|
+
if ((semconvStability & 1 /* STABLE */) ===
|
|
92
|
+
1 /* STABLE */) {
|
|
93
|
+
span.setAttribute(semantic_conventions_1.ATTR_ERROR_TYPE, error.name);
|
|
94
|
+
}
|
|
116
95
|
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message });
|
|
117
96
|
span.recordException(error);
|
|
118
97
|
};
|
|
@@ -120,7 +99,7 @@ exports.setSpanWithError = setSpanWithError;
|
|
|
120
99
|
/**
|
|
121
100
|
* Adds attributes for request content-length and content-encoding HTTP headers
|
|
122
101
|
* @param { IncomingMessage } Request object whose headers will be analyzed
|
|
123
|
-
* @param {
|
|
102
|
+
* @param { Attributes } Attributes object to be modified
|
|
124
103
|
*/
|
|
125
104
|
const setRequestContentLengthAttribute = (request, attributes) => {
|
|
126
105
|
const length = getContentLength(request.headers);
|
|
@@ -137,7 +116,9 @@ exports.setRequestContentLengthAttribute = setRequestContentLengthAttribute;
|
|
|
137
116
|
/**
|
|
138
117
|
* Adds attributes for response content-length and content-encoding HTTP headers
|
|
139
118
|
* @param { IncomingMessage } Response object whose headers will be analyzed
|
|
140
|
-
* @param {
|
|
119
|
+
* @param { Attributes } Attributes object to be modified
|
|
120
|
+
*
|
|
121
|
+
* @deprecated this is for an older version of semconv. It is retained for compatibility using OTEL_SEMCONV_STABILITY_OPT_IN
|
|
141
122
|
*/
|
|
142
123
|
const setResponseContentLengthAttribute = (response, attributes) => {
|
|
143
124
|
const length = getContentLength(response.headers);
|
|
@@ -258,32 +239,55 @@ exports.extractHostnameAndPort = extractHostnameAndPort;
|
|
|
258
239
|
/**
|
|
259
240
|
* Returns outgoing request attributes scoped to the options passed to the request
|
|
260
241
|
* @param {ParsedRequestOptions} requestOptions the same options used to make the request
|
|
261
|
-
* @param {{ component: string, hostname: string, hookAttributes?:
|
|
242
|
+
* @param {{ component: string, hostname: string, hookAttributes?: Attributes }} options used to pass data needed to create attributes
|
|
243
|
+
* @param {SemconvStability} semconvStability determines which semconv version to use
|
|
262
244
|
*/
|
|
263
|
-
const getOutgoingRequestAttributes = (requestOptions, options) => {
|
|
264
|
-
var _a;
|
|
245
|
+
const getOutgoingRequestAttributes = (requestOptions, options, semconvStability) => {
|
|
246
|
+
var _a, _b;
|
|
265
247
|
const hostname = options.hostname;
|
|
266
248
|
const port = options.port;
|
|
267
|
-
const
|
|
268
|
-
const
|
|
249
|
+
const method = (_a = requestOptions.method) !== null && _a !== void 0 ? _a : 'GET';
|
|
250
|
+
const normalizedMethod = normalizeMethod(method);
|
|
269
251
|
const headers = requestOptions.headers || {};
|
|
270
252
|
const userAgent = headers['user-agent'];
|
|
271
|
-
const
|
|
272
|
-
|
|
253
|
+
const urlFull = (0, exports.getAbsoluteUrl)(requestOptions, headers, `${options.component}:`);
|
|
254
|
+
const oldAttributes = {
|
|
255
|
+
[semantic_conventions_1.SEMATTRS_HTTP_URL]: urlFull,
|
|
273
256
|
[semantic_conventions_1.SEMATTRS_HTTP_METHOD]: method,
|
|
274
257
|
[semantic_conventions_1.SEMATTRS_HTTP_TARGET]: requestOptions.path || '/',
|
|
275
258
|
[semantic_conventions_1.SEMATTRS_NET_PEER_NAME]: hostname,
|
|
276
|
-
[semantic_conventions_1.SEMATTRS_HTTP_HOST]: (
|
|
259
|
+
[semantic_conventions_1.SEMATTRS_HTTP_HOST]: (_b = headers.host) !== null && _b !== void 0 ? _b : `${hostname}:${port}`,
|
|
260
|
+
};
|
|
261
|
+
const newAttributes = {
|
|
262
|
+
// Required attributes
|
|
263
|
+
[semantic_conventions_1.ATTR_HTTP_REQUEST_METHOD]: normalizedMethod,
|
|
264
|
+
[semantic_conventions_1.ATTR_SERVER_ADDRESS]: hostname,
|
|
265
|
+
[semantic_conventions_1.ATTR_SERVER_PORT]: Number(port),
|
|
266
|
+
[semantic_conventions_1.ATTR_URL_FULL]: urlFull,
|
|
267
|
+
// leaving out protocol version, it is not yet negotiated
|
|
268
|
+
// leaving out protocol name, it is only required when protocol version is set
|
|
269
|
+
// retries and redirects not supported
|
|
270
|
+
// Opt-in attributes left off for now
|
|
277
271
|
};
|
|
272
|
+
// conditionally required if request method required case normalization
|
|
273
|
+
if (method !== normalizedMethod) {
|
|
274
|
+
newAttributes[semantic_conventions_1.ATTR_HTTP_REQUEST_METHOD_ORIGINAL] = method;
|
|
275
|
+
}
|
|
278
276
|
if (userAgent !== undefined) {
|
|
279
|
-
|
|
277
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_HTTP_USER_AGENT] = userAgent;
|
|
278
|
+
}
|
|
279
|
+
switch (semconvStability) {
|
|
280
|
+
case 1 /* STABLE */:
|
|
281
|
+
return Object.assign(newAttributes, options.hookAttributes);
|
|
282
|
+
case 2 /* OLD */:
|
|
283
|
+
return Object.assign(oldAttributes, options.hookAttributes);
|
|
280
284
|
}
|
|
281
|
-
return Object.assign(
|
|
285
|
+
return Object.assign(oldAttributes, newAttributes, options.hookAttributes);
|
|
282
286
|
};
|
|
283
287
|
exports.getOutgoingRequestAttributes = getOutgoingRequestAttributes;
|
|
284
288
|
/**
|
|
285
289
|
* Returns outgoing request Metric attributes scoped to the request data
|
|
286
|
-
* @param {
|
|
290
|
+
* @param {Attributes} spanAttributes the span attributes
|
|
287
291
|
*/
|
|
288
292
|
const getOutgoingRequestMetricAttributes = (spanAttributes) => {
|
|
289
293
|
const metricAttributes = {};
|
|
@@ -313,28 +317,42 @@ exports.setAttributesFromHttpKind = setAttributesFromHttpKind;
|
|
|
313
317
|
/**
|
|
314
318
|
* Returns outgoing request attributes scoped to the response data
|
|
315
319
|
* @param {IncomingMessage} response the response object
|
|
316
|
-
* @param {
|
|
320
|
+
* @param {SemconvStability} semconvStability determines which semconv version to use
|
|
317
321
|
*/
|
|
318
|
-
const getOutgoingRequestAttributesOnResponse = (response) => {
|
|
322
|
+
const getOutgoingRequestAttributesOnResponse = (response, semconvStability) => {
|
|
319
323
|
const { statusCode, statusMessage, httpVersion, socket } = response;
|
|
320
|
-
const
|
|
324
|
+
const oldAttributes = {};
|
|
325
|
+
const stableAttributes = {};
|
|
326
|
+
if (statusCode != null) {
|
|
327
|
+
stableAttributes[semantic_conventions_1.ATTR_HTTP_RESPONSE_STATUS_CODE] = statusCode;
|
|
328
|
+
}
|
|
321
329
|
if (socket) {
|
|
322
330
|
const { remoteAddress, remotePort } = socket;
|
|
323
|
-
|
|
324
|
-
|
|
331
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_NET_PEER_IP] = remoteAddress;
|
|
332
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_NET_PEER_PORT] = remotePort;
|
|
333
|
+
// Recommended
|
|
334
|
+
stableAttributes[semantic_conventions_1.ATTR_NETWORK_PEER_ADDRESS] = remoteAddress;
|
|
335
|
+
stableAttributes[semantic_conventions_1.ATTR_NETWORK_PEER_PORT] = remotePort;
|
|
336
|
+
stableAttributes[semantic_conventions_1.ATTR_NETWORK_PROTOCOL_VERSION] = response.httpVersion;
|
|
325
337
|
}
|
|
326
|
-
(0, exports.setResponseContentLengthAttribute)(response,
|
|
338
|
+
(0, exports.setResponseContentLengthAttribute)(response, oldAttributes);
|
|
327
339
|
if (statusCode) {
|
|
328
|
-
|
|
329
|
-
|
|
340
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_HTTP_STATUS_CODE] = statusCode;
|
|
341
|
+
oldAttributes[AttributeNames_1.AttributeNames.HTTP_STATUS_TEXT] = (statusMessage || '').toUpperCase();
|
|
342
|
+
}
|
|
343
|
+
(0, exports.setAttributesFromHttpKind)(httpVersion, oldAttributes);
|
|
344
|
+
switch (semconvStability) {
|
|
345
|
+
case 1 /* STABLE */:
|
|
346
|
+
return stableAttributes;
|
|
347
|
+
case 2 /* OLD */:
|
|
348
|
+
return oldAttributes;
|
|
330
349
|
}
|
|
331
|
-
|
|
332
|
-
return attributes;
|
|
350
|
+
return Object.assign(oldAttributes, stableAttributes);
|
|
333
351
|
};
|
|
334
352
|
exports.getOutgoingRequestAttributesOnResponse = getOutgoingRequestAttributesOnResponse;
|
|
335
353
|
/**
|
|
336
354
|
* Returns outgoing request Metric attributes scoped to the response data
|
|
337
|
-
* @param {
|
|
355
|
+
* @param {Attributes} spanAttributes the span attributes
|
|
338
356
|
*/
|
|
339
357
|
const getOutgoingRequestMetricAttributesOnResponse = (spanAttributes) => {
|
|
340
358
|
const metricAttributes = {};
|
|
@@ -346,24 +364,162 @@ const getOutgoingRequestMetricAttributesOnResponse = (spanAttributes) => {
|
|
|
346
364
|
return metricAttributes;
|
|
347
365
|
};
|
|
348
366
|
exports.getOutgoingRequestMetricAttributesOnResponse = getOutgoingRequestMetricAttributesOnResponse;
|
|
367
|
+
function parseHostHeader(hostHeader, proto) {
|
|
368
|
+
const parts = hostHeader.split(':');
|
|
369
|
+
// no semicolon implies ipv4 dotted syntax or host name without port
|
|
370
|
+
// x.x.x.x
|
|
371
|
+
// example.com
|
|
372
|
+
if (parts.length === 1) {
|
|
373
|
+
if (proto === 'http') {
|
|
374
|
+
return { host: parts[0], port: '80' };
|
|
375
|
+
}
|
|
376
|
+
if (proto === 'https') {
|
|
377
|
+
return { host: parts[0], port: '443' };
|
|
378
|
+
}
|
|
379
|
+
return { host: parts[0] };
|
|
380
|
+
}
|
|
381
|
+
// single semicolon implies ipv4 dotted syntax or host name with port
|
|
382
|
+
// x.x.x.x:yyyy
|
|
383
|
+
// example.com:yyyy
|
|
384
|
+
if (parts.length === 2) {
|
|
385
|
+
return {
|
|
386
|
+
host: parts[0],
|
|
387
|
+
port: parts[1],
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
// more than 2 parts implies ipv6 syntax with multiple colons
|
|
391
|
+
// [x:x:x:x:x:x:x:x]
|
|
392
|
+
// [x:x:x:x:x:x:x:x]:yyyy
|
|
393
|
+
if (parts[0].startsWith('[')) {
|
|
394
|
+
if (parts[parts.length - 1].endsWith(']')) {
|
|
395
|
+
if (proto === 'http') {
|
|
396
|
+
return { host: hostHeader, port: '80' };
|
|
397
|
+
}
|
|
398
|
+
if (proto === 'https') {
|
|
399
|
+
return { host: hostHeader, port: '443' };
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
else if (parts[parts.length - 2].endsWith(']')) {
|
|
403
|
+
return {
|
|
404
|
+
host: parts.slice(0, -1).join(':'),
|
|
405
|
+
port: parts[parts.length - 1],
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
// if nothing above matches just return the host header
|
|
410
|
+
return { host: hostHeader };
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Get server.address and port according to http semconv 1.27
|
|
414
|
+
* https://github.com/open-telemetry/semantic-conventions/blob/bf0a2c1134f206f034408b201dbec37960ed60ec/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes
|
|
415
|
+
*/
|
|
416
|
+
function getServerAddress(request, component) {
|
|
417
|
+
const forwardedHeader = request.headers['forwarded'];
|
|
418
|
+
if (forwardedHeader) {
|
|
419
|
+
for (const entry of forwardedParse(forwardedHeader)) {
|
|
420
|
+
if (entry.host) {
|
|
421
|
+
return parseHostHeader(entry.host, entry.proto);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
const xForwardedHost = request.headers['x-forwarded-host'];
|
|
426
|
+
if (typeof xForwardedHost === 'string') {
|
|
427
|
+
if (typeof request.headers['x-forwarded-proto'] === 'string') {
|
|
428
|
+
return parseHostHeader(xForwardedHost, request.headers['x-forwarded-proto']);
|
|
429
|
+
}
|
|
430
|
+
if (Array.isArray(request.headers['x-forwarded-proto'])) {
|
|
431
|
+
return parseHostHeader(xForwardedHost, request.headers['x-forwarded-proto'][0]);
|
|
432
|
+
}
|
|
433
|
+
return parseHostHeader(xForwardedHost);
|
|
434
|
+
}
|
|
435
|
+
else if (Array.isArray(xForwardedHost) &&
|
|
436
|
+
typeof xForwardedHost[0] === 'string' &&
|
|
437
|
+
xForwardedHost[0].length > 0) {
|
|
438
|
+
if (typeof request.headers['x-forwarded-proto'] === 'string') {
|
|
439
|
+
return parseHostHeader(xForwardedHost[0], request.headers['x-forwarded-proto']);
|
|
440
|
+
}
|
|
441
|
+
if (Array.isArray(request.headers['x-forwarded-proto'])) {
|
|
442
|
+
return parseHostHeader(xForwardedHost[0], request.headers['x-forwarded-proto'][0]);
|
|
443
|
+
}
|
|
444
|
+
return parseHostHeader(xForwardedHost[0]);
|
|
445
|
+
}
|
|
446
|
+
const host = request.headers['host'];
|
|
447
|
+
if (typeof host === 'string' && host.length > 0) {
|
|
448
|
+
return parseHostHeader(host, component);
|
|
449
|
+
}
|
|
450
|
+
return null;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Get server.address and port according to http semconv 1.27
|
|
454
|
+
* https://github.com/open-telemetry/semantic-conventions/blob/bf0a2c1134f206f034408b201dbec37960ed60ec/docs/http/http-spans.md#setting-serveraddress-and-serverport-attributes
|
|
455
|
+
*/
|
|
456
|
+
function getRemoteClientAddress(request) {
|
|
457
|
+
const forwardedHeader = request.headers['forwarded'];
|
|
458
|
+
if (forwardedHeader) {
|
|
459
|
+
for (const entry of forwardedParse(forwardedHeader)) {
|
|
460
|
+
if (entry.for) {
|
|
461
|
+
return entry.for;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
const xForwardedFor = request.headers['x-forwarded-for'];
|
|
466
|
+
if (typeof xForwardedFor === 'string') {
|
|
467
|
+
return xForwardedFor;
|
|
468
|
+
}
|
|
469
|
+
else if (Array.isArray(xForwardedFor)) {
|
|
470
|
+
return xForwardedFor[0];
|
|
471
|
+
}
|
|
472
|
+
const remote = request.socket.remoteAddress;
|
|
473
|
+
if (remote) {
|
|
474
|
+
return remote;
|
|
475
|
+
}
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
exports.getRemoteClientAddress = getRemoteClientAddress;
|
|
349
479
|
/**
|
|
350
480
|
* Returns incoming request attributes scoped to the request data
|
|
351
481
|
* @param {IncomingMessage} request the request object
|
|
352
|
-
* @param {{ component: string, serverName?: string, hookAttributes?:
|
|
482
|
+
* @param {{ component: string, serverName?: string, hookAttributes?: Attributes }} options used to pass data needed to create attributes
|
|
483
|
+
* @param {SemconvStability} semconvStability determines which semconv version to use
|
|
353
484
|
*/
|
|
354
485
|
const getIncomingRequestAttributes = (request, options) => {
|
|
355
486
|
const headers = request.headers;
|
|
356
487
|
const userAgent = headers['user-agent'];
|
|
357
488
|
const ips = headers['x-forwarded-for'];
|
|
358
|
-
const method = request.method || 'GET';
|
|
359
489
|
const httpVersion = request.httpVersion;
|
|
360
490
|
const requestUrl = request.url ? url.parse(request.url) : null;
|
|
361
491
|
const host = (requestUrl === null || requestUrl === void 0 ? void 0 : requestUrl.host) || headers.host;
|
|
362
492
|
const hostname = (requestUrl === null || requestUrl === void 0 ? void 0 : requestUrl.hostname) ||
|
|
363
493
|
(host === null || host === void 0 ? void 0 : host.replace(/^(.*)(:[0-9]{1,5})/, '$1')) ||
|
|
364
494
|
'localhost';
|
|
495
|
+
const method = request.method;
|
|
496
|
+
const normalizedMethod = normalizeMethod(method);
|
|
497
|
+
const serverAddress = getServerAddress(request, options.component);
|
|
365
498
|
const serverName = options.serverName;
|
|
366
|
-
const
|
|
499
|
+
const remoteClientAddress = getRemoteClientAddress(request);
|
|
500
|
+
const newAttributes = {
|
|
501
|
+
[semantic_conventions_1.ATTR_HTTP_REQUEST_METHOD]: normalizedMethod,
|
|
502
|
+
[semantic_conventions_1.ATTR_URL_SCHEME]: options.component,
|
|
503
|
+
[semantic_conventions_1.ATTR_SERVER_ADDRESS]: serverAddress === null || serverAddress === void 0 ? void 0 : serverAddress.host,
|
|
504
|
+
[semantic_conventions_1.ATTR_NETWORK_PEER_ADDRESS]: request.socket.remoteAddress,
|
|
505
|
+
[semantic_conventions_1.ATTR_NETWORK_PEER_PORT]: request.socket.remotePort,
|
|
506
|
+
[semantic_conventions_1.ATTR_NETWORK_PROTOCOL_VERSION]: request.httpVersion,
|
|
507
|
+
[semantic_conventions_1.ATTR_USER_AGENT_ORIGINAL]: userAgent,
|
|
508
|
+
};
|
|
509
|
+
if ((requestUrl === null || requestUrl === void 0 ? void 0 : requestUrl.pathname) != null) {
|
|
510
|
+
newAttributes[semantic_conventions_1.ATTR_URL_PATH] = requestUrl.pathname;
|
|
511
|
+
}
|
|
512
|
+
if (remoteClientAddress != null) {
|
|
513
|
+
newAttributes[semantic_conventions_1.ATTR_CLIENT_ADDRESS] = remoteClientAddress;
|
|
514
|
+
}
|
|
515
|
+
if ((serverAddress === null || serverAddress === void 0 ? void 0 : serverAddress.port) != null) {
|
|
516
|
+
newAttributes[semantic_conventions_1.ATTR_SERVER_PORT] = Number(serverAddress.port);
|
|
517
|
+
}
|
|
518
|
+
// conditionally required if request method required case normalization
|
|
519
|
+
if (method !== normalizedMethod) {
|
|
520
|
+
newAttributes[semantic_conventions_1.ATTR_HTTP_REQUEST_METHOD_ORIGINAL] = method;
|
|
521
|
+
}
|
|
522
|
+
const oldAttributes = {
|
|
367
523
|
[semantic_conventions_1.SEMATTRS_HTTP_URL]: (0, exports.getAbsoluteUrl)(requestUrl, headers, `${options.component}:`),
|
|
368
524
|
[semantic_conventions_1.SEMATTRS_HTTP_HOST]: host,
|
|
369
525
|
[semantic_conventions_1.SEMATTRS_NET_HOST_NAME]: hostname,
|
|
@@ -371,25 +527,31 @@ const getIncomingRequestAttributes = (request, options) => {
|
|
|
371
527
|
[semantic_conventions_1.SEMATTRS_HTTP_SCHEME]: options.component,
|
|
372
528
|
};
|
|
373
529
|
if (typeof ips === 'string') {
|
|
374
|
-
|
|
530
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_HTTP_CLIENT_IP] = ips.split(',')[0];
|
|
375
531
|
}
|
|
376
532
|
if (typeof serverName === 'string') {
|
|
377
|
-
|
|
533
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_HTTP_SERVER_NAME] = serverName;
|
|
378
534
|
}
|
|
379
535
|
if (requestUrl) {
|
|
380
|
-
|
|
536
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_HTTP_TARGET] = requestUrl.path || '/';
|
|
381
537
|
}
|
|
382
538
|
if (userAgent !== undefined) {
|
|
383
|
-
|
|
539
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_HTTP_USER_AGENT] = userAgent;
|
|
540
|
+
}
|
|
541
|
+
(0, exports.setRequestContentLengthAttribute)(request, oldAttributes);
|
|
542
|
+
(0, exports.setAttributesFromHttpKind)(httpVersion, oldAttributes);
|
|
543
|
+
switch (options.semconvStability) {
|
|
544
|
+
case 1 /* STABLE */:
|
|
545
|
+
return Object.assign(newAttributes, options.hookAttributes);
|
|
546
|
+
case 2 /* OLD */:
|
|
547
|
+
return Object.assign(oldAttributes, options.hookAttributes);
|
|
384
548
|
}
|
|
385
|
-
|
|
386
|
-
(0, exports.setAttributesFromHttpKind)(httpVersion, attributes);
|
|
387
|
-
return Object.assign(attributes, options.hookAttributes);
|
|
549
|
+
return Object.assign(oldAttributes, newAttributes, options.hookAttributes);
|
|
388
550
|
};
|
|
389
551
|
exports.getIncomingRequestAttributes = getIncomingRequestAttributes;
|
|
390
552
|
/**
|
|
391
553
|
* Returns incoming request Metric attributes scoped to the request data
|
|
392
|
-
* @param {
|
|
554
|
+
* @param {Attributes} spanAttributes the span attributes
|
|
393
555
|
* @param {{ component: string }} options used to pass data needed to create attributes
|
|
394
556
|
*/
|
|
395
557
|
const getIncomingRequestMetricAttributes = (spanAttributes) => {
|
|
@@ -407,31 +569,41 @@ exports.getIncomingRequestMetricAttributes = getIncomingRequestMetricAttributes;
|
|
|
407
569
|
* Returns incoming request attributes scoped to the response data
|
|
408
570
|
* @param {(ServerResponse & { socket: Socket; })} response the response object
|
|
409
571
|
*/
|
|
410
|
-
const getIncomingRequestAttributesOnResponse = (request, response) => {
|
|
572
|
+
const getIncomingRequestAttributesOnResponse = (request, response, semconvStability) => {
|
|
411
573
|
// take socket from the request,
|
|
412
574
|
// since it may be detached from the response object in keep-alive mode
|
|
413
575
|
const { socket } = request;
|
|
414
576
|
const { statusCode, statusMessage } = response;
|
|
577
|
+
const newAttributes = {
|
|
578
|
+
[semantic_conventions_1.ATTR_HTTP_RESPONSE_STATUS_CODE]: statusCode,
|
|
579
|
+
};
|
|
415
580
|
const rpcMetadata = (0, core_1.getRPCMetadata)(api_1.context.active());
|
|
416
|
-
const
|
|
581
|
+
const oldAttributes = {};
|
|
417
582
|
if (socket) {
|
|
418
583
|
const { localAddress, localPort, remoteAddress, remotePort } = socket;
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
584
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_NET_HOST_IP] = localAddress;
|
|
585
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_NET_HOST_PORT] = localPort;
|
|
586
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_NET_PEER_IP] = remoteAddress;
|
|
587
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_NET_PEER_PORT] = remotePort;
|
|
423
588
|
}
|
|
424
|
-
|
|
425
|
-
|
|
589
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_HTTP_STATUS_CODE] = statusCode;
|
|
590
|
+
oldAttributes[AttributeNames_1.AttributeNames.HTTP_STATUS_TEXT] = (statusMessage || '').toUpperCase();
|
|
426
591
|
if ((rpcMetadata === null || rpcMetadata === void 0 ? void 0 : rpcMetadata.type) === core_1.RPCType.HTTP && rpcMetadata.route !== undefined) {
|
|
427
|
-
|
|
592
|
+
oldAttributes[semantic_conventions_1.SEMATTRS_HTTP_ROUTE] = rpcMetadata.route;
|
|
593
|
+
newAttributes[semantic_conventions_1.ATTR_HTTP_ROUTE] = rpcMetadata.route;
|
|
594
|
+
}
|
|
595
|
+
switch (semconvStability) {
|
|
596
|
+
case 1 /* STABLE */:
|
|
597
|
+
return newAttributes;
|
|
598
|
+
case 2 /* OLD */:
|
|
599
|
+
return oldAttributes;
|
|
428
600
|
}
|
|
429
|
-
return
|
|
601
|
+
return Object.assign(oldAttributes, newAttributes);
|
|
430
602
|
};
|
|
431
603
|
exports.getIncomingRequestAttributesOnResponse = getIncomingRequestAttributesOnResponse;
|
|
432
604
|
/**
|
|
433
605
|
* Returns incoming request Metric attributes scoped to the request data
|
|
434
|
-
* @param {
|
|
606
|
+
* @param {Attributes} spanAttributes the span attributes
|
|
435
607
|
*/
|
|
436
608
|
const getIncomingRequestMetricAttributesOnResponse = (spanAttributes) => {
|
|
437
609
|
const metricAttributes = {};
|
|
@@ -445,6 +617,19 @@ const getIncomingRequestMetricAttributesOnResponse = (spanAttributes) => {
|
|
|
445
617
|
return metricAttributes;
|
|
446
618
|
};
|
|
447
619
|
exports.getIncomingRequestMetricAttributesOnResponse = getIncomingRequestMetricAttributesOnResponse;
|
|
620
|
+
const getIncomingStableRequestMetricAttributesOnResponse = (spanAttributes) => {
|
|
621
|
+
const metricAttributes = {};
|
|
622
|
+
if (spanAttributes[semantic_conventions_1.ATTR_HTTP_ROUTE] !== undefined) {
|
|
623
|
+
metricAttributes[semantic_conventions_1.ATTR_HTTP_ROUTE] = spanAttributes[semantic_conventions_1.SEMATTRS_HTTP_ROUTE];
|
|
624
|
+
}
|
|
625
|
+
// required if and only if one was sent, same as span requirement
|
|
626
|
+
if (spanAttributes[semantic_conventions_1.ATTR_HTTP_RESPONSE_STATUS_CODE]) {
|
|
627
|
+
metricAttributes[semantic_conventions_1.ATTR_HTTP_RESPONSE_STATUS_CODE] =
|
|
628
|
+
spanAttributes[semantic_conventions_1.ATTR_HTTP_RESPONSE_STATUS_CODE];
|
|
629
|
+
}
|
|
630
|
+
return metricAttributes;
|
|
631
|
+
};
|
|
632
|
+
exports.getIncomingStableRequestMetricAttributesOnResponse = getIncomingStableRequestMetricAttributesOnResponse;
|
|
448
633
|
function headerCapture(type, headers) {
|
|
449
634
|
const normalizedHeaders = new Map();
|
|
450
635
|
for (let i = 0, len = headers.length; i < len; i++) {
|
|
@@ -472,4 +657,27 @@ function headerCapture(type, headers) {
|
|
|
472
657
|
};
|
|
473
658
|
}
|
|
474
659
|
exports.headerCapture = headerCapture;
|
|
660
|
+
const KNOWN_METHODS = new Set([
|
|
661
|
+
// methods from https://www.rfc-editor.org/rfc/rfc9110.html#name-methods
|
|
662
|
+
'GET',
|
|
663
|
+
'HEAD',
|
|
664
|
+
'POST',
|
|
665
|
+
'PUT',
|
|
666
|
+
'DELETE',
|
|
667
|
+
'CONNECT',
|
|
668
|
+
'OPTIONS',
|
|
669
|
+
'TRACE',
|
|
670
|
+
// PATCH from https://www.rfc-editor.org/rfc/rfc5789.html
|
|
671
|
+
'PATCH',
|
|
672
|
+
]);
|
|
673
|
+
function normalizeMethod(method) {
|
|
674
|
+
if (method == null) {
|
|
675
|
+
return 'GET';
|
|
676
|
+
}
|
|
677
|
+
const upper = method.toUpperCase();
|
|
678
|
+
if (KNOWN_METHODS.has(upper)) {
|
|
679
|
+
return upper;
|
|
680
|
+
}
|
|
681
|
+
return '_OTHER';
|
|
682
|
+
}
|
|
475
683
|
//# sourceMappingURL=utils.js.map
|