UNPKG

@sentry/node

Version:

Sentry Node SDK using OpenTelemetry for performance instrumentation

173 lines (142 loc) 5.78 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const api = require('@opentelemetry/api'); const instrumentationHttp = require('@opentelemetry/instrumentation-http'); const core = require('@sentry/core'); const nodeCore = require('@sentry/node-core'); const INTEGRATION_NAME = 'Http'; const INSTRUMENTATION_NAME = '@opentelemetry_sentry-patched/instrumentation-http'; const instrumentSentryHttp = nodeCore.generateInstrumentOnce( `${INTEGRATION_NAME}.sentry`, options => { return new nodeCore.SentryHttpInstrumentation(options); }, ); const instrumentOtelHttp = nodeCore.generateInstrumentOnce(INTEGRATION_NAME, config => { const instrumentation = new instrumentationHttp.HttpInstrumentation({ ...config, // This is hard-coded and can never be overridden by the user disableIncomingRequestInstrumentation: true, }); // We want to update the logger namespace so we can better identify what is happening here try { instrumentation['_diag'] = api.diag.createComponentLogger({ namespace: INSTRUMENTATION_NAME, }); // @ts-expect-error We are writing a read-only property here... instrumentation.instrumentationName = INSTRUMENTATION_NAME; } catch { // ignore errors here... } return instrumentation; }); /** Exported only for tests. */ function _shouldUseOtelHttpInstrumentation( options, clientOptions = {}, ) { // If `spans` is passed in, it takes precedence // Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true` or spans are not enabled if (typeof options.spans === 'boolean') { return options.spans; } if (clientOptions.skipOpenTelemetrySetup) { return false; } // IMPORTANT: We only disable span instrumentation when spans are not enabled _and_ we are on Node 22+, // as otherwise the necessary diagnostics channel is not available yet if (!core.hasSpansEnabled(clientOptions) && nodeCore.NODE_VERSION.major >= 22) { return false; } return true; } /** * The http integration instruments Node's internal http and https modules. * It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span. */ const httpIntegration = core.defineIntegration((options = {}) => { const spans = options.spans ?? true; const disableIncomingRequestSpans = options.disableIncomingRequestSpans; const serverOptions = { sessions: options.trackIncomingRequestsAsSessions, sessionFlushingDelayMS: options.sessionFlushingDelayMS, ignoreRequestBody: options.ignoreIncomingRequestBody, maxRequestBodySize: options.maxIncomingRequestBodySize, } ; const serverSpansOptions = { ignoreIncomingRequests: options.ignoreIncomingRequests, ignoreStaticAssets: options.ignoreStaticAssets, ignoreStatusCodes: options.dropSpansForIncomingRequestStatusCodes, instrumentation: options.instrumentation, onSpanCreated: options.incomingRequestSpanHook, } ; const server = nodeCore.httpServerIntegration(serverOptions); const serverSpans = nodeCore.httpServerSpansIntegration(serverSpansOptions); const enableServerSpans = spans && !disableIncomingRequestSpans; return { name: INTEGRATION_NAME, setup(client) { const clientOptions = client.getOptions(); if (enableServerSpans && core.hasSpansEnabled(clientOptions)) { serverSpans.setup(client); } }, setupOnce() { const clientOptions = (core.getClient()?.getOptions() || {}) ; const useOtelHttpInstrumentation = _shouldUseOtelHttpInstrumentation(options, clientOptions); server.setupOnce(); const sentryHttpInstrumentationOptions = { breadcrumbs: options.breadcrumbs, propagateTraceInOutgoingRequests: !useOtelHttpInstrumentation, ignoreOutgoingRequests: options.ignoreOutgoingRequests, } ; // This is Sentry-specific instrumentation for outgoing request breadcrumbs & trace propagation instrumentSentryHttp(sentryHttpInstrumentationOptions); // This is the "regular" OTEL instrumentation that emits outgoing request spans if (useOtelHttpInstrumentation) { const instrumentationConfig = getConfigWithDefaults(options); instrumentOtelHttp(instrumentationConfig); } }, processEvent(event) { // Note: We always run this, even if spans are disabled // The reason being that e.g. the remix integration disables span creation here but still wants to use the ignore status codes option return serverSpans.processEvent(event); }, }; }); function getConfigWithDefaults(options = {}) { const instrumentationConfig = { ignoreOutgoingRequestHook: request => { const url = nodeCore.getRequestUrl(request); if (!url) { return false; } const _ignoreOutgoingRequests = options.ignoreOutgoingRequests; if (_ignoreOutgoingRequests?.(url, request)) { return true; } return false; }, requireParentforOutgoingSpans: false, requestHook: (span, req) => { nodeCore.addOriginToSpan(span, 'auto.http.otel.http'); options.instrumentation?.requestHook?.(span, req); }, responseHook: (span, res) => { options.instrumentation?.responseHook?.(span, res); }, applyCustomAttributesOnSpan: ( span, request, response, ) => { options.instrumentation?.applyCustomAttributesOnSpan?.(span, request, response); }, } ; return instrumentationConfig; } exports._shouldUseOtelHttpInstrumentation = _shouldUseOtelHttpInstrumentation; exports.httpIntegration = httpIntegration; exports.instrumentOtelHttp = instrumentOtelHttp; exports.instrumentSentryHttp = instrumentSentryHttp; //# sourceMappingURL=http.js.map