@sentry/nextjs
Version:
Official Sentry SDK for Next.js
89 lines (86 loc) • 3.86 kB
JavaScript
import { getActiveSpan, getRootSpan, getCapturedScopesOnSpan, setCapturedScopesOnSpan, Scope, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, withIsolationScope, getIsolationScope, withScope, winterCGHeadersToDict, propagationContextFromHeaders, handleCallbackErrors, setHttpStatus, captureException } from '@sentry/core';
import { isRedirectNavigationError, isNotFoundNavigationError } from './nextNavigationErrorUtils.js';
import { waitUntil, flushSafelyWithTimeout } from './utils/responseEnd.js';
import { commonObjectToIsolationScope } from './utils/tracingUtils.js';
import { HTTP_ROUTE } from '@sentry/conventions/attributes';
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({
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
[SEMANTIC_ATTRIBUTE_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) => {
if (isRedirectNavigationError(error)) ; else if (isNotFoundNavigationError(error)) {
if (activeSpan) {
setHttpStatus(activeSpan, 404);
}
if (rootSpan) {
setHttpStatus(rootSpan, 404);
}
} else {
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