12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- import { _nullishCoalesce, _optionalChain } from '@sentry/utils';
- import { addTracingExtensions, withIsolationScope, getCurrentScope, startSpanManual, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, handleCallbackErrors, captureException } from '@sentry/core';
- import { winterCGHeadersToDict, propagationContextFromHeaders } from '@sentry/utils';
- import { isNotFoundNavigationError, isRedirectNavigationError } from './nextNavigationErrorUtils.js';
- import { commonObjectToPropagationContext } from './utils/commonObjectTracing.js';
- import { flushQueue } from './utils/responseEnd.js';
- /**
- * Wraps an `app` directory server component with Sentry error instrumentation.
- */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- function wrapServerComponentWithSentry(
- appDirComponent,
- context,
- ) {
- addTracingExtensions();
- const { componentRoute, componentType } = context;
- // Even though users may define server components as async functions, for the client bundles
- // Next.js will turn them into synchronous functions and it will transform any `await`s into instances of the `use`
- // hook. 🤯
- return new Proxy(appDirComponent, {
- apply: (originalFunction, thisArg, args) => {
- // TODO: If we ever allow withIsolationScope to take a scope, we should pass a scope here that is shared between all of the server components, similar to what `commonObjectToPropagationContext` does.
- return withIsolationScope(isolationScope => {
- const completeHeadersDict = context.headers
- ? winterCGHeadersToDict(context.headers)
- : {};
- isolationScope.setSDKProcessingMetadata({
- request: {
- headers: completeHeadersDict,
- },
- });
- const incomingPropagationContext = propagationContextFromHeaders(
- // eslint-disable-next-line deprecation/deprecation
- _nullishCoalesce(context.sentryTraceHeader, () => ( completeHeadersDict['sentry-trace'])),
- // eslint-disable-next-line deprecation/deprecation
- _nullishCoalesce(context.baggageHeader, () => ( completeHeadersDict['baggage'])),
- );
- const propagationContext = commonObjectToPropagationContext(context.headers, incomingPropagationContext);
- isolationScope.setPropagationContext(propagationContext);
- getCurrentScope().setPropagationContext(propagationContext);
- return startSpanManual(
- {
- op: 'function.nextjs',
- name: `${componentType} Server Component (${componentRoute})`,
- attributes: {
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component',
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.nextjs',
- },
- },
- span => {
- return handleCallbackErrors(
- () => originalFunction.apply(thisArg, args),
- error => {
- if (isNotFoundNavigationError(error)) {
- // We don't want to report "not-found"s
- _optionalChain([span, 'optionalAccess', _ => _.setStatus, 'call', _2 => _2('not_found')]);
- } else if (isRedirectNavigationError(error)) {
- // We don't want to report redirects
- _optionalChain([span, 'optionalAccess', _3 => _3.setStatus, 'call', _4 => _4('ok')]);
- } else {
- _optionalChain([span, 'optionalAccess', _5 => _5.setStatus, 'call', _6 => _6('internal_error')]);
- captureException(error, {
- mechanism: {
- handled: false,
- },
- });
- }
- },
- () => {
- _optionalChain([span, 'optionalAccess', _7 => _7.end, 'call', _8 => _8()]);
- // flushQueue should not throw
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- flushQueue();
- },
- );
- },
- );
- });
- },
- });
- }
- export { wrapServerComponentWithSentry };
- //# sourceMappingURL=wrapServerComponentWithSentry.js.map
|