UNPKG

@sentry/nextjs

Version:
101 lines (98 loc) • 4.58 kB
import { getActiveSpan, getRootSpan, getCapturedScopesOnSpan, setCapturedScopesOnSpan, Scope, withIsolationScope, getIsolationScope, withScope, winterCGHeadersToDict, propagationContextFromHeaders, handleCallbackErrors, setHttpStatus, SPAN_STATUS_ERROR, captureException } from '@sentry/core'; import { getAuthInterruptStatusCode, isRedirectNavigationError, isNotFoundNavigationError, isPrerenderControlFlowError } from './nextNavigationErrorUtils.js'; import { waitUntil, flushSafelyWithTimeout } from './utils/responseEnd.js'; import { commonObjectToIsolationScope } from './utils/tracingUtils.js'; import { HTTP_ROUTE, SENTRY_OP, SENTRY_SEGMENT_NAME_SOURCE } from '@sentry/conventions/attributes'; import { HTTP_SERVER } from '@sentry/conventions/op'; function wrapRouteHandlerWithSentry(routeHandler, context) { const { method, parameterizedRoute, headers } = context; return new Proxy(routeHandler, { apply: async (originalFunction, thisArg, args) => { const activeSpan = getActiveSpan(); const rootSpan = activeSpan ? getRootSpan(activeSpan) : void 0; let edgeRuntimeIsolationScopeOverride; if (rootSpan && process.env.NEXT_RUNTIME === "edge") { const isolationScope = commonObjectToIsolationScope(headers); const { scope } = getCapturedScopesOnSpan(rootSpan); setCapturedScopesOnSpan(rootSpan, scope ?? new Scope(), isolationScope); edgeRuntimeIsolationScopeOverride = isolationScope; rootSpan.updateName(`${method} ${parameterizedRoute}`); rootSpan.setAttributes({ [SENTRY_SEGMENT_NAME_SOURCE]: "route", [SENTRY_OP]: HTTP_SERVER, [HTTP_ROUTE]: parameterizedRoute }); } return withIsolationScope( process.env.NEXT_RUNTIME === "edge" ? edgeRuntimeIsolationScopeOverride : getIsolationScope(), () => { return withScope(async (scope) => { scope.setTransactionName(`${method} ${parameterizedRoute}`); if (process.env.NEXT_RUNTIME === "edge") { const completeHeadersDict = headers ? winterCGHeadersToDict(headers) : {}; const incomingPropagationContext = propagationContextFromHeaders( completeHeadersDict["sentry-trace"], completeHeadersDict["baggage"] ); scope.setPropagationContext(incomingPropagationContext); scope.setSDKProcessingMetadata({ normalizedRequest: { method, headers: completeHeadersDict } }); } const response = await handleCallbackErrors( () => originalFunction.apply(thisArg, args), (error) => { const authInterruptStatusCode = getAuthInterruptStatusCode(error); if (isRedirectNavigationError(error)) ; else if (isNotFoundNavigationError(error)) { if (activeSpan) { setHttpStatus(activeSpan, 404); } if (rootSpan) { setHttpStatus(rootSpan, 404); } } else if (authInterruptStatusCode) { if (activeSpan) { setHttpStatus(activeSpan, authInterruptStatusCode); } if (rootSpan) { setHttpStatus(rootSpan, authInterruptStatusCode); } } else if (isPrerenderControlFlowError(error)) ; else { const errorStatus = { code: SPAN_STATUS_ERROR, message: "internal_error" }; activeSpan?.setStatus(errorStatus); rootSpan?.setStatus(errorStatus); captureException(error, { mechanism: { handled: false, type: "auto.function.nextjs.route_handler" } }); } }, () => { waitUntil(flushSafelyWithTimeout()); } ); try { if (response.status) { if (activeSpan) { setHttpStatus(activeSpan, response.status); } if (rootSpan) { setHttpStatus(rootSpan, response.status); } } } catch { } return response; }); } ); } }); } export { wrapRouteHandlerWithSentry }; //# sourceMappingURL=wrapRouteHandlerWithSentry.js.map