rittenhop-dev/versions/5.94.2/node_modules/@sentry/node/cjs/integrations/http.js

390 lines
13 KiB
JavaScript
Raw Normal View History

2024-09-23 19:40:12 -04:00
var {
_optionalChain
} = require('@sentry/utils');
Object.defineProperty(exports, '__esModule', { value: true });
const core = require('@sentry/core');
const utils = require('@sentry/utils');
const debugBuild = require('../debug-build.js');
const nodeVersion = require('../nodeVersion.js');
const http = require('./utils/http.js');
const _httpIntegration = ((options = {}) => {
const { breadcrumbs, tracing, shouldCreateSpanForRequest } = options;
const convertedOptions = {
breadcrumbs,
tracing:
tracing === false
? false
: utils.dropUndefinedKeys({
// If tracing is forced to `true`, we don't want to set `enableIfHasTracingEnabled`
enableIfHasTracingEnabled: tracing === true ? undefined : true,
shouldCreateSpanForRequest,
}),
};
// eslint-disable-next-line deprecation/deprecation
return new Http(convertedOptions) ;
}) ;
/**
* The http module integration instruments Node's internal http module. It creates breadcrumbs, spans for outgoing
* http requests, and attaches trace data when tracing is enabled via its `tracing` option.
*
* By default, this will always create breadcrumbs, and will create spans if tracing is enabled.
*/
const httpIntegration = core.defineIntegration(_httpIntegration);
/**
* The http module integration instruments Node's internal http module. It creates breadcrumbs, transactions for outgoing
* http requests and attaches trace data when tracing is enabled via its `tracing` option.
*
* @deprecated Use `httpIntegration()` instead.
*/
class Http {
/**
* @inheritDoc
*/
static __initStatic() {this.id = 'Http';}
/**
* @inheritDoc
*/
// eslint-disable-next-line deprecation/deprecation
__init() {this.name = Http.id;}
/**
* @inheritDoc
*/
constructor(options = {}) {Http.prototype.__init.call(this);
this._breadcrumbs = typeof options.breadcrumbs === 'undefined' ? true : options.breadcrumbs;
this._tracing = !options.tracing ? undefined : options.tracing === true ? {} : options.tracing;
}
/**
* @inheritDoc
*/
setupOnce(
_addGlobalEventProcessor,
// eslint-disable-next-line deprecation/deprecation
setupOnceGetCurrentHub,
) {
// eslint-disable-next-line deprecation/deprecation
const clientOptions = _optionalChain([setupOnceGetCurrentHub, 'call', _ => _(), 'access', _2 => _2.getClient, 'call', _3 => _3(), 'optionalAccess', _4 => _4.getOptions, 'call', _5 => _5()]);
// If `tracing` is not explicitly set, we default this based on whether or not tracing is enabled.
// But for compatibility, we only do that if `enableIfHasTracingEnabled` is set.
const shouldCreateSpans = _shouldCreateSpans(this._tracing, clientOptions);
// No need to instrument if we don't want to track anything
if (!this._breadcrumbs && !shouldCreateSpans) {
return;
}
// Do not auto-instrument for other instrumenter
if (clientOptions && clientOptions.instrumenter !== 'sentry') {
debugBuild.DEBUG_BUILD && utils.logger.log('HTTP Integration is skipped because of instrumenter configuration.');
return;
}
const shouldCreateSpanForRequest = _getShouldCreateSpanForRequest(shouldCreateSpans, this._tracing, clientOptions);
// eslint-disable-next-line deprecation/deprecation
const tracePropagationTargets = _optionalChain([clientOptions, 'optionalAccess', _6 => _6.tracePropagationTargets]) || _optionalChain([this, 'access', _7 => _7._tracing, 'optionalAccess', _8 => _8.tracePropagationTargets]);
// eslint-disable-next-line @typescript-eslint/no-var-requires
const httpModule = require('http');
const wrappedHttpHandlerMaker = _createWrappedRequestMethodFactory(
httpModule,
this._breadcrumbs,
shouldCreateSpanForRequest,
tracePropagationTargets,
);
utils.fill(httpModule, 'get', wrappedHttpHandlerMaker);
utils.fill(httpModule, 'request', wrappedHttpHandlerMaker);
// NOTE: Prior to Node 9, `https` used internals of `http` module, thus we don't patch it.
// If we do, we'd get double breadcrumbs and double spans for `https` calls.
// It has been changed in Node 9, so for all versions equal and above, we patch `https` separately.
if (nodeVersion.NODE_VERSION.major > 8) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const httpsModule = require('https');
const wrappedHttpsHandlerMaker = _createWrappedRequestMethodFactory(
httpsModule,
this._breadcrumbs,
shouldCreateSpanForRequest,
tracePropagationTargets,
);
utils.fill(httpsModule, 'get', wrappedHttpsHandlerMaker);
utils.fill(httpsModule, 'request', wrappedHttpsHandlerMaker);
}
}
}Http.__initStatic();
// for ease of reading below
/**
* Function which creates a function which creates wrapped versions of internal `request` and `get` calls within `http`
* and `https` modules. (NB: Not a typo - this is a creator^2!)
*
* @param breadcrumbsEnabled Whether or not to record outgoing requests as breadcrumbs
* @param tracingEnabled Whether or not to record outgoing requests as tracing spans
*
* @returns A function which accepts the exiting handler and returns a wrapped handler
*/
function _createWrappedRequestMethodFactory(
httpModule,
breadcrumbsEnabled,
shouldCreateSpanForRequest,
tracePropagationTargets,
) {
// We're caching results so we don't have to recompute regexp every time we create a request.
const createSpanUrlMap = new utils.LRUMap(100);
const headersUrlMap = new utils.LRUMap(100);
const shouldCreateSpan = (url) => {
if (shouldCreateSpanForRequest === undefined) {
return true;
}
const cachedDecision = createSpanUrlMap.get(url);
if (cachedDecision !== undefined) {
return cachedDecision;
}
const decision = shouldCreateSpanForRequest(url);
createSpanUrlMap.set(url, decision);
return decision;
};
const shouldAttachTraceData = (url) => {
if (tracePropagationTargets === undefined) {
return true;
}
const cachedDecision = headersUrlMap.get(url);
if (cachedDecision !== undefined) {
return cachedDecision;
}
const decision = utils.stringMatchesSomePattern(url, tracePropagationTargets);
headersUrlMap.set(url, decision);
return decision;
};
/**
* Captures Breadcrumb based on provided request/response pair
*/
function addRequestBreadcrumb(
event,
requestSpanData,
req,
res,
) {
// eslint-disable-next-line deprecation/deprecation
if (!core.getCurrentHub().getIntegration(Http)) {
return;
}
core.addBreadcrumb(
{
category: 'http',
data: {
status_code: res && res.statusCode,
...requestSpanData,
},
type: 'http',
},
{
event,
request: req,
response: res,
},
);
}
return function wrappedRequestMethodFactory(originalRequestMethod) {
return function wrappedMethod( ...args) {
const requestArgs = http.normalizeRequestArgs(httpModule, args);
const requestOptions = requestArgs[0];
// eslint-disable-next-line deprecation/deprecation
const rawRequestUrl = http.extractRawUrl(requestOptions);
const requestUrl = http.extractUrl(requestOptions);
const client = core.getClient();
// we don't want to record requests to Sentry as either breadcrumbs or spans, so just use the original method
if (core.isSentryRequestUrl(requestUrl, client)) {
return originalRequestMethod.apply(httpModule, requestArgs);
}
const scope = core.getCurrentScope();
const isolationScope = core.getIsolationScope();
const parentSpan = core.getActiveSpan();
const data = getRequestSpanData(requestUrl, requestOptions);
const requestSpan = shouldCreateSpan(rawRequestUrl)
? // eslint-disable-next-line deprecation/deprecation
_optionalChain([parentSpan, 'optionalAccess', _9 => _9.startChild, 'call', _10 => _10({
op: 'http.client',
origin: 'auto.http.node.http',
description: `${data['http.method']} ${data.url}`,
data,
})])
: undefined;
if (client && shouldAttachTraceData(rawRequestUrl)) {
const { traceId, spanId, sampled, dsc } = {
...isolationScope.getPropagationContext(),
...scope.getPropagationContext(),
};
const sentryTraceHeader = requestSpan
? core.spanToTraceHeader(requestSpan)
: utils.generateSentryTraceHeader(traceId, spanId, sampled);
const sentryBaggageHeader = utils.dynamicSamplingContextToSentryBaggageHeader(
dsc ||
(requestSpan
? core.getDynamicSamplingContextFromSpan(requestSpan)
: core.getDynamicSamplingContextFromClient(traceId, client, scope)),
);
addHeadersToRequestOptions(requestOptions, requestUrl, sentryTraceHeader, sentryBaggageHeader);
} else {
debugBuild.DEBUG_BUILD &&
utils.logger.log(
`[Tracing] Not adding sentry-trace header to outgoing request (${requestUrl}) due to mismatching tracePropagationTargets option.`,
);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
return originalRequestMethod
.apply(httpModule, requestArgs)
.once('response', function ( res) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const req = this;
if (breadcrumbsEnabled) {
addRequestBreadcrumb('response', data, req, res);
}
if (requestSpan) {
if (res.statusCode) {
core.setHttpStatus(requestSpan, res.statusCode);
}
requestSpan.updateName(
http.cleanSpanDescription(core.spanToJSON(requestSpan).description || '', requestOptions, req) || '',
);
requestSpan.end();
}
})
.once('error', function () {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const req = this;
if (breadcrumbsEnabled) {
addRequestBreadcrumb('error', data, req);
}
if (requestSpan) {
core.setHttpStatus(requestSpan, 500);
requestSpan.updateName(
http.cleanSpanDescription(core.spanToJSON(requestSpan).description || '', requestOptions, req) || '',
);
requestSpan.end();
}
});
};
};
}
function addHeadersToRequestOptions(
requestOptions,
requestUrl,
sentryTraceHeader,
sentryBaggageHeader,
) {
// Don't overwrite sentry-trace and baggage header if it's already set.
const headers = requestOptions.headers || {};
if (headers['sentry-trace']) {
return;
}
debugBuild.DEBUG_BUILD &&
utils.logger.log(`[Tracing] Adding sentry-trace header ${sentryTraceHeader} to outgoing request to "${requestUrl}": `);
requestOptions.headers = {
...requestOptions.headers,
'sentry-trace': sentryTraceHeader,
// Setting a header to `undefined` will crash in node so we only set the baggage header when it's defined
...(sentryBaggageHeader &&
sentryBaggageHeader.length > 0 && { baggage: normalizeBaggageHeader(requestOptions, sentryBaggageHeader) }),
};
}
function getRequestSpanData(requestUrl, requestOptions) {
const method = requestOptions.method || 'GET';
const data = {
url: requestUrl,
'http.method': method,
};
if (requestOptions.hash) {
// strip leading "#"
data['http.fragment'] = requestOptions.hash.substring(1);
}
if (requestOptions.search) {
// strip leading "?"
data['http.query'] = requestOptions.search.substring(1);
}
return data;
}
function normalizeBaggageHeader(
requestOptions,
sentryBaggageHeader,
) {
if (!requestOptions.headers || !requestOptions.headers.baggage) {
return sentryBaggageHeader;
} else if (!sentryBaggageHeader) {
return requestOptions.headers.baggage ;
} else if (Array.isArray(requestOptions.headers.baggage)) {
return [...requestOptions.headers.baggage, sentryBaggageHeader];
}
// Type-cast explanation:
// Technically this the following could be of type `(number | string)[]` but for the sake of simplicity
// we say this is undefined behaviour, since it would not be baggage spec conform if the user did this.
return [requestOptions.headers.baggage, sentryBaggageHeader] ;
}
/** Exported for tests only. */
function _shouldCreateSpans(
tracingOptions,
clientOptions,
) {
return tracingOptions === undefined
? false
: tracingOptions.enableIfHasTracingEnabled
? core.hasTracingEnabled(clientOptions)
: true;
}
/** Exported for tests only. */
function _getShouldCreateSpanForRequest(
shouldCreateSpans,
tracingOptions,
clientOptions,
) {
const handler = shouldCreateSpans
? // eslint-disable-next-line deprecation/deprecation
_optionalChain([tracingOptions, 'optionalAccess', _11 => _11.shouldCreateSpanForRequest]) || _optionalChain([clientOptions, 'optionalAccess', _12 => _12.shouldCreateSpanForRequest])
: () => false;
return handler;
}
exports.Http = Http;
exports._getShouldCreateSpanForRequest = _getShouldCreateSpanForRequest;
exports._shouldCreateSpans = _shouldCreateSpans;
exports.httpIntegration = httpIntegration;
//# sourceMappingURL=http.js.map