@sentry/nextjs
Version:
Official Sentry SDK for Next.js
85 lines (77 loc) • 3.4 kB
JavaScript
import { _nullishCoalesce, _optionalChain } from '@sentry/utils';
import { addTracingExtensions, runWithAsyncContext, getCurrentScope, startSpan, handleCallbackErrors, captureException } from '@sentry/core';
import { tracingContextFromHeaders, winterCGHeadersToDict } from '@sentry/utils';
import { isRedirectNavigationError } from './nextNavigationErrorUtils.js';
import { platformSupportsStreaming } from './utils/platformSupportsStreaming.js';
import { flushQueue } from './utils/responseEnd.js';
/**
* Wraps a Next.js route handler with performance and error instrumentation.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function wrapRouteHandlerWithSentry(
routeHandler,
context,
) {
addTracingExtensions();
// eslint-disable-next-line deprecation/deprecation
const { method, parameterizedRoute, baggageHeader, sentryTraceHeader, headers } = context;
return new Proxy(routeHandler, {
apply: (originalFunction, thisArg, args) => {
return runWithAsyncContext(async () => {
const { traceparentData, dynamicSamplingContext, propagationContext } = tracingContextFromHeaders(
_nullishCoalesce(_nullishCoalesce(sentryTraceHeader, () => ( _optionalChain([headers, 'optionalAccess', _ => _.get, 'call', _2 => _2('sentry-trace')]))), () => ( undefined)),
_nullishCoalesce(baggageHeader, () => ( _optionalChain([headers, 'optionalAccess', _3 => _3.get, 'call', _4 => _4('baggage')]))),
);
getCurrentScope().setPropagationContext(propagationContext);
let result;
try {
result = await startSpan(
{
op: 'http.server',
name: `${method} ${parameterizedRoute}`,
status: 'ok',
...traceparentData,
metadata: {
request: {
headers: headers ? winterCGHeadersToDict(headers) : undefined,
},
source: 'route',
dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext,
},
},
async span => {
const response = await handleCallbackErrors(
() => originalFunction.apply(thisArg, args),
error => {
// Next.js throws errors when calling `redirect()`. We don't wanna report these.
if (!isRedirectNavigationError(error)) {
captureException(error, {
mechanism: {
handled: false,
},
});
}
},
);
try {
_optionalChain([span, 'optionalAccess', _5 => _5.setHttpStatus, 'call', _6 => _6(response.status)]);
} catch (e) {
// best effort
}
return response;
},
);
} finally {
if (!platformSupportsStreaming() || process.env.NEXT_RUNTIME === 'edge') {
// 1. Edge tranpsort requires manual flushing
// 2. Lambdas require manual flushing to prevent execution freeze before the event is sent
await flushQueue();
}
}
return result;
});
},
});
}
export { wrapRouteHandlerWithSentry };
//# sourceMappingURL=wrapRouteHandlerWithSentry.js.map