UNPKG

@sentry/nextjs

Version:
94 lines (91 loc) 4.31 kB
import { debug, withIsolationScope, getActiveSpan, continueTrace, httpRequestToRequestData, parseStringToURLObject, startSpanManual, isURLObjectRelative, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, setHttpStatus, objectify, captureException, isString } from '@sentry/core'; import { waitUntil, flushSafelyWithTimeout } from '../utils/responseEnd.js'; import { dropNextjsRootContext, escapeNextjsTracing } from '../utils/tracingUtils.js'; import { HTTP_ROUTE, URL_PATH, URL_FULL } from '@sentry/conventions/attributes'; function wrapApiHandlerWithSentry(apiHandler, parameterizedRoute) { return new Proxy(apiHandler, { apply: (wrappingTarget, thisArg, args) => { dropNextjsRootContext(); return escapeNextjsTracing(() => { const [req, res] = args; if (!req) { debug.log( `Wrapped API handler on route "${parameterizedRoute}" was not passed a request object. Will not instrument.` ); return wrappingTarget.apply(thisArg, args); } else if (!res) { debug.log( `Wrapped API handler on route "${parameterizedRoute}" was not passed a response object. Will not instrument.` ); return wrappingTarget.apply(thisArg, args); } if (req.__withSentry_applied__) { return wrappingTarget.apply(thisArg, args); } req.__withSentry_applied__ = true; return withIsolationScope((isolationScope) => { const continueTraceIfNoActiveSpan = getActiveSpan() ? (_opts, callback) => callback() : continueTrace; return continueTraceIfNoActiveSpan( { sentryTrace: req.headers && isString(req.headers["sentry-trace"]) ? req.headers["sentry-trace"] : void 0, baggage: req.headers?.baggage }, () => { const reqMethod = `${(req.method || "GET").toUpperCase()} `; const normalizedRequest = httpRequestToRequestData(req); isolationScope.setSDKProcessingMetadata({ normalizedRequest }); isolationScope.setTransactionName(`${reqMethod}${parameterizedRoute}`); const requestUrl = normalizedRequest.url || req.url; const urlObject = requestUrl ? parseStringToURLObject(requestUrl) : void 0; return startSpanManual( { name: `${reqMethod}${parameterizedRoute}`, op: "http.server", forceTransaction: true, attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route", [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.nextjs", [URL_FULL]: urlObject && !isURLObjectRelative(urlObject) ? urlObject.href : void 0, [URL_PATH]: urlObject?.pathname, [HTTP_ROUTE]: parameterizedRoute } }, async (span) => { res.end = new Proxy(res.end, { apply(target, thisArg2, argArray) { setHttpStatus(span, res.statusCode); span.end(); waitUntil(flushSafelyWithTimeout()); return target.apply(thisArg2, argArray); } }); try { return await wrappingTarget.apply(thisArg, args); } catch (e) { const objectifiedErr = objectify(e); captureException(objectifiedErr, { mechanism: { type: "auto.http.nextjs.api_handler", handled: false, data: { wrapped_handler: wrappingTarget.name, function: "withSentry" } } }); setHttpStatus(span, 500); span.end(); await flushSafelyWithTimeout(); throw objectifiedErr; } } ); } ); }); }); } }); } export { wrapApiHandlerWithSentry }; //# sourceMappingURL=wrapApiHandlerWithSentry.js.map