UNPKG

@sentry/node

Version:

Sentry Node SDK using OpenTelemetry for performance instrumentation

142 lines (123 loc) • 5.03 kB
var { _optionalChain } = require('@sentry/utils'); Object.defineProperty(exports, '__esModule', { value: true }); const instrumentationExpress = require('@opentelemetry/instrumentation-express'); const core = require('@sentry/core'); const utils = require('@sentry/utils'); const debugBuild = require('../../debug-build.js'); const instrument = require('../../otel/instrument.js'); const addOriginToSpan = require('../../utils/addOriginToSpan.js'); const ensureIsWrapped = require('../../utils/ensureIsWrapped.js'); const INTEGRATION_NAME = 'Express'; const instrumentExpress = instrument.generateInstrumentOnce( INTEGRATION_NAME, () => new instrumentationExpress.ExpressInstrumentation({ requestHook(span) { addOriginToSpan.addOriginToSpan(span, 'auto.http.otel.express'); const attributes = core.spanToJSON(span).data || {}; // this is one of: middleware, request_handler, router const type = attributes['express.type']; if (type) { span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_OP, `${type}.express`); } // Also update the name, we don't need to "middleware - " prefix const name = attributes['express.name']; if (typeof name === 'string') { span.updateName(name); } }, spanNameHook(info, defaultName) { if (core.getIsolationScope() === core.getDefaultIsolationScope()) { debugBuild.DEBUG_BUILD && utils.logger.warn('Isolation scope is still default isolation scope - skipping setting transactionName'); return defaultName; } if (info.layerType === 'request_handler') { // type cast b/c Otel unfortunately types info.request as any :( const req = info.request ; const method = req.method ? req.method.toUpperCase() : 'GET'; core.getIsolationScope().setTransactionName(`${method} ${info.route}`); } return defaultName; }, }), ); const _expressIntegration = (() => { return { name: INTEGRATION_NAME, setupOnce() { instrumentExpress(); }, }; }) ; /** * Express integration * * Capture tracing data for express. * In order to capture exceptions, you have to call `setupExpressErrorHandler(app)` before any other middleware and after all controllers. */ const expressIntegration = core.defineIntegration(_expressIntegration); /** * An Express-compatible error handler. */ function expressErrorHandler(options) { return function sentryErrorMiddleware( error, _req, res, next, ) { const shouldHandleError = _optionalChain([options, 'optionalAccess', _ => _.shouldHandleError]) || defaultShouldHandleError; if (shouldHandleError(error)) { const client = core.getClient(); if (client && client.getOptions().autoSessionTracking) { // Check if the `SessionFlusher` is instantiated on the client to go into this branch that marks the // `requestSession.status` as `Crashed`, and this check is necessary because the `SessionFlusher` is only // instantiated when the the`requestHandler` middleware is initialised, which indicates that we should be // running in SessionAggregates mode const isSessionAggregatesMode = client['_sessionFlusher'] !== undefined; if (isSessionAggregatesMode) { const requestSession = core.getIsolationScope().getRequestSession(); // If an error bubbles to the `errorHandler`, then this is an unhandled error, and should be reported as a // Crashed session. The `_requestSession.status` is checked to ensure that this error is happening within // the bounds of a request, and if so the status is updated if (requestSession && requestSession.status !== undefined) { requestSession.status = 'crashed'; } } } const eventId = core.captureException(error, { mechanism: { type: 'middleware', handled: false } }); (res ).sentry = eventId; next(error); return; } next(error); }; } /** * Setup an error handler for Express. * The error handler must be before any other middleware and after all controllers. */ function setupExpressErrorHandler( app, options, ) { app.use(expressErrorHandler(options)); ensureIsWrapped.ensureIsWrapped(app.use, 'express'); } function getStatusCodeFromResponse(error) { const statusCode = error.status || error.statusCode || error.status_code || (error.output && error.output.statusCode); return statusCode ? parseInt(statusCode , 10) : 500; } /** Returns true if response code is internal server error */ function defaultShouldHandleError(error) { const status = getStatusCodeFromResponse(error); return status >= 500; } exports.expressErrorHandler = expressErrorHandler; exports.expressIntegration = expressIntegration; exports.instrumentExpress = instrumentExpress; exports.setupExpressErrorHandler = setupExpressErrorHandler; //# sourceMappingURL=express.js.map