@opentelemetry/instrumentation-http
Version:
OpenTelemetry instrumentation for `node:http` and `node:https` http client and server modules
590 lines • 31.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpInstrumentation = void 0;
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const api_1 = require("@opentelemetry/api");
const core_1 = require("@opentelemetry/core");
const url = require("url");
const version_1 = require("./version");
const instrumentation_1 = require("@opentelemetry/instrumentation");
const events_1 = require("events");
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
const utils_1 = require("./utils");
/**
* `node:http` and `node:https` instrumentation for OpenTelemetry
*/
class HttpInstrumentation extends instrumentation_1.InstrumentationBase {
/** keep track on spans not ended */
_spanNotEnded = new WeakSet();
_headerCapture;
_semconvStability = instrumentation_1.SemconvStability.OLD;
constructor(config = {}) {
super('@opentelemetry/instrumentation-http', version_1.VERSION, config);
this._headerCapture = this._createHeaderCapture();
this._semconvStability = (0, instrumentation_1.semconvStabilityFromStr)('http', process.env.OTEL_SEMCONV_STABILITY_OPT_IN);
}
_updateMetricInstruments() {
this._oldHttpServerDurationHistogram = this.meter.createHistogram('http.server.duration', {
description: 'Measures the duration of inbound HTTP requests.',
unit: 'ms',
valueType: api_1.ValueType.DOUBLE,
});
this._oldHttpClientDurationHistogram = this.meter.createHistogram('http.client.duration', {
description: 'Measures the duration of outbound HTTP requests.',
unit: 'ms',
valueType: api_1.ValueType.DOUBLE,
});
this._stableHttpServerDurationHistogram = this.meter.createHistogram(semantic_conventions_1.METRIC_HTTP_SERVER_REQUEST_DURATION, {
description: 'Duration of HTTP server requests.',
unit: 's',
valueType: api_1.ValueType.DOUBLE,
advice: {
explicitBucketBoundaries: [
0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5,
7.5, 10,
],
},
});
this._stableHttpClientDurationHistogram = this.meter.createHistogram(semantic_conventions_1.METRIC_HTTP_CLIENT_REQUEST_DURATION, {
description: 'Duration of HTTP client requests.',
unit: 's',
valueType: api_1.ValueType.DOUBLE,
advice: {
explicitBucketBoundaries: [
0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5,
7.5, 10,
],
},
});
}
_recordServerDuration(durationMs, oldAttributes, stableAttributes) {
if (this._semconvStability & instrumentation_1.SemconvStability.OLD) {
// old histogram is counted in MS
this._oldHttpServerDurationHistogram.record(durationMs, oldAttributes);
}
if (this._semconvStability & instrumentation_1.SemconvStability.STABLE) {
// stable histogram is counted in S
this._stableHttpServerDurationHistogram.record(durationMs / 1000, stableAttributes);
}
}
_recordClientDuration(durationMs, oldAttributes, stableAttributes) {
if (this._semconvStability & instrumentation_1.SemconvStability.OLD) {
// old histogram is counted in MS
this._oldHttpClientDurationHistogram.record(durationMs, oldAttributes);
}
if (this._semconvStability & instrumentation_1.SemconvStability.STABLE) {
// stable histogram is counted in S
this._stableHttpClientDurationHistogram.record(durationMs / 1000, stableAttributes);
}
}
setConfig(config = {}) {
super.setConfig(config);
this._headerCapture = this._createHeaderCapture();
}
init() {
return [this._getHttpsInstrumentation(), this._getHttpInstrumentation()];
}
_getHttpInstrumentation() {
return new instrumentation_1.InstrumentationNodeModuleDefinition('http', ['*'], (moduleExports) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isESM = moduleExports[Symbol.toStringTag] === 'Module';
if (!this.getConfig().disableOutgoingRequestInstrumentation) {
const patchedRequest = this._wrap(moduleExports, 'request', this._getPatchOutgoingRequestFunction('http'));
const patchedGet = this._wrap(moduleExports, 'get', this._getPatchOutgoingGetFunction(patchedRequest));
if (isESM) {
// To handle `import http from 'http'`, which returns the default
// export, we need to set `module.default.*`.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
moduleExports.default.request = patchedRequest;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
moduleExports.default.get = patchedGet;
}
}
if (!this.getConfig().disableIncomingRequestInstrumentation) {
this._wrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction('http'));
}
return moduleExports;
}, (moduleExports) => {
if (moduleExports === undefined)
return;
if (!this.getConfig().disableOutgoingRequestInstrumentation) {
this._unwrap(moduleExports, 'request');
this._unwrap(moduleExports, 'get');
}
if (!this.getConfig().disableIncomingRequestInstrumentation) {
this._unwrap(moduleExports.Server.prototype, 'emit');
}
});
}
_getHttpsInstrumentation() {
return new instrumentation_1.InstrumentationNodeModuleDefinition('https', ['*'], (moduleExports) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isESM = moduleExports[Symbol.toStringTag] === 'Module';
if (!this.getConfig().disableOutgoingRequestInstrumentation) {
const patchedRequest = this._wrap(moduleExports, 'request', this._getPatchHttpsOutgoingRequestFunction('https'));
const patchedGet = this._wrap(moduleExports, 'get', this._getPatchHttpsOutgoingGetFunction(patchedRequest));
if (isESM) {
// To handle `import https from 'https'`, which returns the default
// export, we need to set `module.default.*`.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
moduleExports.default.request = patchedRequest;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
moduleExports.default.get = patchedGet;
}
}
if (!this.getConfig().disableIncomingRequestInstrumentation) {
this._wrap(moduleExports.Server.prototype, 'emit', this._getPatchIncomingRequestFunction('https'));
}
return moduleExports;
}, (moduleExports) => {
if (moduleExports === undefined)
return;
if (!this.getConfig().disableOutgoingRequestInstrumentation) {
this._unwrap(moduleExports, 'request');
this._unwrap(moduleExports, 'get');
}
if (!this.getConfig().disableIncomingRequestInstrumentation) {
this._unwrap(moduleExports.Server.prototype, 'emit');
}
});
}
/**
* Creates spans for incoming requests, restoring spans' context if applied.
*/
_getPatchIncomingRequestFunction(component) {
return (original) => {
return this._incomingRequestFunction(component, original);
};
}
/**
* Creates spans for outgoing requests, sending spans' context for distributed
* tracing.
*/
_getPatchOutgoingRequestFunction(component) {
return (original) => {
return this._outgoingRequestFunction(component, original);
};
}
_getPatchOutgoingGetFunction(clientRequest) {
return (_original) => {
// Re-implement http.get. This needs to be done (instead of using
// getPatchOutgoingRequestFunction to patch it) because we need to
// set the trace context header before the returned http.ClientRequest is
// ended. The Node.js docs state that the only differences between
// request and get are that (1) get defaults to the HTTP GET method and
// (2) the returned request object is ended immediately. The former is
// already true (at least in supported Node versions up to v10), so we
// simply follow the latter. Ref:
// https://nodejs.org/dist/latest/docs/api/http.html#http_http_get_options_callback
// https://github.com/googleapis/cloud-trace-nodejs/blob/master/src/instrumentations/instrumentation-http.ts#L198
return function outgoingGetRequest(options, ...args) {
const req = clientRequest(options, ...args);
req.end();
return req;
};
};
}
/** Patches HTTPS outgoing requests */
_getPatchHttpsOutgoingRequestFunction(component) {
return (original) => {
const instrumentation = this;
return function httpsOutgoingRequest(
// eslint-disable-next-line node/no-unsupported-features/node-builtins
options, ...args) {
// Makes sure options will have default HTTPS parameters
if (component === 'https' &&
typeof options === 'object' &&
options?.constructor?.name !== 'URL') {
options = Object.assign({}, options);
instrumentation._setDefaultOptions(options);
}
return instrumentation._getPatchOutgoingRequestFunction(component)(original)(options, ...args);
};
};
}
_setDefaultOptions(options) {
options.protocol = options.protocol || 'https:';
options.port = options.port || 443;
}
/** Patches HTTPS outgoing get requests */
_getPatchHttpsOutgoingGetFunction(clientRequest) {
return (original) => {
const instrumentation = this;
return function httpsOutgoingRequest(
// eslint-disable-next-line node/no-unsupported-features/node-builtins
options, ...args) {
return instrumentation._getPatchOutgoingGetFunction(clientRequest)(original)(options, ...args);
};
};
}
/**
* Attach event listeners to a client request to end span and add span attributes.
*
* @param request The original request object.
* @param span representing the current operation
* @param startTime representing the start time of the request to calculate duration in Metric
* @param oldMetricAttributes metric attributes for old semantic conventions
* @param stableMetricAttributes metric attributes for new semantic conventions
*/
_traceClientRequest(request, span, startTime, oldMetricAttributes, stableMetricAttributes) {
if (this.getConfig().requestHook) {
this._callRequestHook(span, request);
}
/**
* Determines if the request has errored or the response has ended/errored.
*/
let responseFinished = false;
/*
* User 'response' event listeners can be added before our listener,
* force our listener to be the first, so response emitter is bound
* before any user listeners are added to it.
*/
request.prependListener('response', (response) => {
this._diag.debug('outgoingRequest on response()');
if (request.listenerCount('response') <= 1) {
response.resume();
}
const responseAttributes = (0, utils_1.getOutgoingRequestAttributesOnResponse)(response, this._semconvStability);
span.setAttributes(responseAttributes);
oldMetricAttributes = Object.assign(oldMetricAttributes, (0, utils_1.getOutgoingRequestMetricAttributesOnResponse)(responseAttributes));
stableMetricAttributes = Object.assign(stableMetricAttributes, (0, utils_1.getOutgoingStableRequestMetricAttributesOnResponse)(responseAttributes));
if (this.getConfig().responseHook) {
this._callResponseHook(span, response);
}
this._headerCapture.client.captureRequestHeaders(span, header => request.getHeader(header));
this._headerCapture.client.captureResponseHeaders(span, header => response.headers[header]);
api_1.context.bind(api_1.context.active(), response);
const endHandler = () => {
this._diag.debug('outgoingRequest on end()');
if (responseFinished) {
return;
}
responseFinished = true;
let status;
if (response.aborted && !response.complete) {
status = { code: api_1.SpanStatusCode.ERROR };
}
else {
// behaves same for new and old semconv
status = {
code: (0, utils_1.parseResponseStatus)(api_1.SpanKind.CLIENT, response.statusCode),
};
}
span.setStatus(status);
if (this.getConfig().applyCustomAttributesOnSpan) {
(0, instrumentation_1.safeExecuteInTheMiddle)(() => this.getConfig().applyCustomAttributesOnSpan(span, request, response), () => { }, true);
}
this._closeHttpSpan(span, api_1.SpanKind.CLIENT, startTime, oldMetricAttributes, stableMetricAttributes);
};
response.on('end', endHandler);
response.on(events_1.errorMonitor, (error) => {
this._diag.debug('outgoingRequest on error()', error);
if (responseFinished) {
return;
}
responseFinished = true;
(0, utils_1.setSpanWithError)(span, error, this._semconvStability);
span.setStatus({
code: api_1.SpanStatusCode.ERROR,
message: error.message,
});
this._closeHttpSpan(span, api_1.SpanKind.CLIENT, startTime, oldMetricAttributes, stableMetricAttributes);
});
});
request.on('close', () => {
this._diag.debug('outgoingRequest on request close()');
if (request.aborted || responseFinished) {
return;
}
responseFinished = true;
this._closeHttpSpan(span, api_1.SpanKind.CLIENT, startTime, oldMetricAttributes, stableMetricAttributes);
});
request.on(events_1.errorMonitor, (error) => {
this._diag.debug('outgoingRequest on request error()', error);
if (responseFinished) {
return;
}
responseFinished = true;
(0, utils_1.setSpanWithError)(span, error, this._semconvStability);
this._closeHttpSpan(span, api_1.SpanKind.CLIENT, startTime, oldMetricAttributes, stableMetricAttributes);
});
this._diag.debug('http.ClientRequest return request');
return request;
}
_incomingRequestFunction(component, original) {
const instrumentation = this;
return function incomingRequest(event, ...args) {
// Only traces request events
if (event !== 'request') {
return original.apply(this, [event, ...args]);
}
const request = args[0];
const response = args[1];
const method = request.method || 'GET';
instrumentation._diag.debug(`${component} instrumentation incomingRequest`);
if ((0, instrumentation_1.safeExecuteInTheMiddle)(() => instrumentation.getConfig().ignoreIncomingRequestHook?.(request), (e) => {
if (e != null) {
instrumentation._diag.error('caught ignoreIncomingRequestHook error: ', e);
}
}, true)) {
return api_1.context.with((0, core_1.suppressTracing)(api_1.context.active()), () => {
api_1.context.bind(api_1.context.active(), request);
api_1.context.bind(api_1.context.active(), response);
return original.apply(this, [event, ...args]);
});
}
const headers = request.headers;
const spanAttributes = (0, utils_1.getIncomingRequestAttributes)(request, {
component: component,
serverName: instrumentation.getConfig().serverName,
hookAttributes: instrumentation._callStartSpanHook(request, instrumentation.getConfig().startIncomingSpanHook),
semconvStability: instrumentation._semconvStability,
enableSyntheticSourceDetection: instrumentation.getConfig().enableSyntheticSourceDetection || false,
}, instrumentation._diag);
const spanOptions = {
kind: api_1.SpanKind.SERVER,
attributes: spanAttributes,
};
const startTime = (0, core_1.hrTime)();
const oldMetricAttributes = (0, utils_1.getIncomingRequestMetricAttributes)(spanAttributes);
// request method and url.scheme are both required span attributes
const stableMetricAttributes = {
[semantic_conventions_1.ATTR_HTTP_REQUEST_METHOD]: spanAttributes[semantic_conventions_1.ATTR_HTTP_REQUEST_METHOD],
[semantic_conventions_1.ATTR_URL_SCHEME]: spanAttributes[semantic_conventions_1.ATTR_URL_SCHEME],
};
// recommended if and only if one was sent, same as span recommendation
if (spanAttributes[semantic_conventions_1.ATTR_NETWORK_PROTOCOL_VERSION]) {
stableMetricAttributes[semantic_conventions_1.ATTR_NETWORK_PROTOCOL_VERSION] =
spanAttributes[semantic_conventions_1.ATTR_NETWORK_PROTOCOL_VERSION];
}
const ctx = api_1.propagation.extract(api_1.ROOT_CONTEXT, headers);
const span = instrumentation._startHttpSpan(method, spanOptions, ctx);
const rpcMetadata = {
type: core_1.RPCType.HTTP,
span,
};
return api_1.context.with((0, core_1.setRPCMetadata)(api_1.trace.setSpan(ctx, span), rpcMetadata), () => {
api_1.context.bind(api_1.context.active(), request);
api_1.context.bind(api_1.context.active(), response);
if (instrumentation.getConfig().requestHook) {
instrumentation._callRequestHook(span, request);
}
if (instrumentation.getConfig().responseHook) {
instrumentation._callResponseHook(span, response);
}
instrumentation._headerCapture.server.captureRequestHeaders(span, header => request.headers[header]);
// After 'error', no further events other than 'close' should be emitted.
let hasError = false;
response.on('close', () => {
if (hasError) {
return;
}
instrumentation._onServerResponseFinish(request, response, span, oldMetricAttributes, stableMetricAttributes, startTime);
});
response.on(events_1.errorMonitor, (err) => {
hasError = true;
instrumentation._onServerResponseError(span, oldMetricAttributes, stableMetricAttributes, startTime, err);
});
return (0, instrumentation_1.safeExecuteInTheMiddle)(() => original.apply(this, [event, ...args]), error => {
if (error) {
(0, utils_1.setSpanWithError)(span, error, instrumentation._semconvStability);
instrumentation._closeHttpSpan(span, api_1.SpanKind.SERVER, startTime, oldMetricAttributes, stableMetricAttributes);
throw error;
}
});
});
};
}
_outgoingRequestFunction(component, original) {
const instrumentation = this;
return function outgoingRequest(options, ...args) {
if (!(0, utils_1.isValidOptionsType)(options)) {
return original.apply(this, [options, ...args]);
}
const extraOptions = typeof args[0] === 'object' &&
(typeof options === 'string' || options instanceof url.URL)
? args.shift()
: undefined;
const { method, invalidUrl, optionsParsed } = (0, utils_1.getRequestInfo)(instrumentation._diag, options, extraOptions);
if ((0, instrumentation_1.safeExecuteInTheMiddle)(() => instrumentation
.getConfig()
.ignoreOutgoingRequestHook?.(optionsParsed), (e) => {
if (e != null) {
instrumentation._diag.error('caught ignoreOutgoingRequestHook error: ', e);
}
}, true)) {
return original.apply(this, [optionsParsed, ...args]);
}
const { hostname, port } = (0, utils_1.extractHostnameAndPort)(optionsParsed);
const attributes = (0, utils_1.getOutgoingRequestAttributes)(optionsParsed, {
component,
port,
hostname,
hookAttributes: instrumentation._callStartSpanHook(optionsParsed, instrumentation.getConfig().startOutgoingSpanHook),
}, instrumentation._semconvStability, instrumentation.getConfig().enableSyntheticSourceDetection || false);
const startTime = (0, core_1.hrTime)();
const oldMetricAttributes = (0, utils_1.getOutgoingRequestMetricAttributes)(attributes);
// request method, server address, and server port are both required span attributes
const stableMetricAttributes = {
[semantic_conventions_1.ATTR_HTTP_REQUEST_METHOD]: attributes[semantic_conventions_1.ATTR_HTTP_REQUEST_METHOD],
[semantic_conventions_1.ATTR_SERVER_ADDRESS]: attributes[semantic_conventions_1.ATTR_SERVER_ADDRESS],
[semantic_conventions_1.ATTR_SERVER_PORT]: attributes[semantic_conventions_1.ATTR_SERVER_PORT],
};
// required if and only if one was sent, same as span requirement
if (attributes[semantic_conventions_1.ATTR_HTTP_RESPONSE_STATUS_CODE]) {
stableMetricAttributes[semantic_conventions_1.ATTR_HTTP_RESPONSE_STATUS_CODE] =
attributes[semantic_conventions_1.ATTR_HTTP_RESPONSE_STATUS_CODE];
}
// recommended if and only if one was sent, same as span recommendation
if (attributes[semantic_conventions_1.ATTR_NETWORK_PROTOCOL_VERSION]) {
stableMetricAttributes[semantic_conventions_1.ATTR_NETWORK_PROTOCOL_VERSION] =
attributes[semantic_conventions_1.ATTR_NETWORK_PROTOCOL_VERSION];
}
const spanOptions = {
kind: api_1.SpanKind.CLIENT,
attributes,
};
const span = instrumentation._startHttpSpan(method, spanOptions);
const parentContext = api_1.context.active();
const requestContext = api_1.trace.setSpan(parentContext, span);
if (!optionsParsed.headers) {
optionsParsed.headers = {};
}
else {
// Make a copy of the headers object to avoid mutating an object the
// caller might have a reference to.
optionsParsed.headers = Object.assign({}, optionsParsed.headers);
}
api_1.propagation.inject(requestContext, optionsParsed.headers);
return api_1.context.with(requestContext, () => {
/*
* The response callback is registered before ClientRequest is bound,
* thus it is needed to bind it before the function call.
*/
const cb = args[args.length - 1];
if (typeof cb === 'function') {
args[args.length - 1] = api_1.context.bind(parentContext, cb);
}
const request = (0, instrumentation_1.safeExecuteInTheMiddle)(() => {
if (invalidUrl) {
// we know that the url is invalid, there's no point in injecting context as it will fail validation.
// Passing in what the user provided will give the user an error that matches what they'd see without
// the instrumentation.
return original.apply(this, [options, ...args]);
}
else {
return original.apply(this, [optionsParsed, ...args]);
}
}, error => {
if (error) {
(0, utils_1.setSpanWithError)(span, error, instrumentation._semconvStability);
instrumentation._closeHttpSpan(span, api_1.SpanKind.CLIENT, startTime, oldMetricAttributes, stableMetricAttributes);
throw error;
}
});
instrumentation._diag.debug(`${component} instrumentation outgoingRequest`);
api_1.context.bind(parentContext, request);
return instrumentation._traceClientRequest(request, span, startTime, oldMetricAttributes, stableMetricAttributes);
});
};
}
_onServerResponseFinish(request, response, span, oldMetricAttributes, stableMetricAttributes, startTime) {
const attributes = (0, utils_1.getIncomingRequestAttributesOnResponse)(request, response, this._semconvStability);
oldMetricAttributes = Object.assign(oldMetricAttributes, (0, utils_1.getIncomingRequestMetricAttributesOnResponse)(attributes));
stableMetricAttributes = Object.assign(stableMetricAttributes, (0, utils_1.getIncomingStableRequestMetricAttributesOnResponse)(attributes));
this._headerCapture.server.captureResponseHeaders(span, header => response.getHeader(header));
span.setAttributes(attributes).setStatus({
code: (0, utils_1.parseResponseStatus)(api_1.SpanKind.SERVER, response.statusCode),
});
const route = attributes[semantic_conventions_1.ATTR_HTTP_ROUTE];
if (route) {
span.updateName(`${request.method || 'GET'} ${route}`);
}
if (this.getConfig().applyCustomAttributesOnSpan) {
(0, instrumentation_1.safeExecuteInTheMiddle)(() => this.getConfig().applyCustomAttributesOnSpan(span, request, response), () => { }, true);
}
this._closeHttpSpan(span, api_1.SpanKind.SERVER, startTime, oldMetricAttributes, stableMetricAttributes);
}
_onServerResponseError(span, oldMetricAttributes, stableMetricAttributes, startTime, error) {
(0, utils_1.setSpanWithError)(span, error, this._semconvStability);
// TODO get error attributes for metrics
this._closeHttpSpan(span, api_1.SpanKind.SERVER, startTime, oldMetricAttributes, stableMetricAttributes);
}
_startHttpSpan(name, options, ctx = api_1.context.active()) {
/*
* If a parent is required but not present, we use a `NoopSpan` to still
* propagate context without recording it.
*/
const requireParent = options.kind === api_1.SpanKind.CLIENT
? this.getConfig().requireParentforOutgoingSpans
: this.getConfig().requireParentforIncomingSpans;
let span;
const currentSpan = api_1.trace.getSpan(ctx);
if (requireParent === true && currentSpan === undefined) {
span = api_1.trace.wrapSpanContext(api_1.INVALID_SPAN_CONTEXT);
}
else if (requireParent === true && currentSpan?.spanContext().isRemote) {
span = currentSpan;
}
else {
span = this.tracer.startSpan(name, options, ctx);
}
this._spanNotEnded.add(span);
return span;
}
_closeHttpSpan(span, spanKind, startTime, oldMetricAttributes, stableMetricAttributes) {
if (!this._spanNotEnded.has(span)) {
return;
}
span.end();
this._spanNotEnded.delete(span);
// Record metrics
const duration = (0, core_1.hrTimeToMilliseconds)((0, core_1.hrTimeDuration)(startTime, (0, core_1.hrTime)()));
if (spanKind === api_1.SpanKind.SERVER) {
this._recordServerDuration(duration, oldMetricAttributes, stableMetricAttributes);
}
else if (spanKind === api_1.SpanKind.CLIENT) {
this._recordClientDuration(duration, oldMetricAttributes, stableMetricAttributes);
}
}
_callResponseHook(span, response) {
(0, instrumentation_1.safeExecuteInTheMiddle)(() => this.getConfig().responseHook(span, response), () => { }, true);
}
_callRequestHook(span, request) {
(0, instrumentation_1.safeExecuteInTheMiddle)(() => this.getConfig().requestHook(span, request), () => { }, true);
}
_callStartSpanHook(request, hookFunc) {
if (typeof hookFunc === 'function') {
return (0, instrumentation_1.safeExecuteInTheMiddle)(() => hookFunc(request), () => { }, true);
}
}
_createHeaderCapture() {
const config = this.getConfig();
return {
client: {
captureRequestHeaders: (0, utils_1.headerCapture)('request', config.headersToSpanAttributes?.client?.requestHeaders ?? []),
captureResponseHeaders: (0, utils_1.headerCapture)('response', config.headersToSpanAttributes?.client?.responseHeaders ?? []),
},
server: {
captureRequestHeaders: (0, utils_1.headerCapture)('request', config.headersToSpanAttributes?.server?.requestHeaders ?? []),
captureResponseHeaders: (0, utils_1.headerCapture)('response', config.headersToSpanAttributes?.server?.responseHeaders ?? []),
},
};
}
}
exports.HttpInstrumentation = HttpInstrumentation;
//# sourceMappingURL=http.js.map