wrapServerComponentWithSentry.js 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. var {
  2. _nullishCoalesce,
  3. _optionalChain
  4. } = require('@sentry/utils');
  5. Object.defineProperty(exports, '__esModule', { value: true });
  6. const core = require('@sentry/core');
  7. const utils = require('@sentry/utils');
  8. const nextNavigationErrorUtils = require('./nextNavigationErrorUtils.js');
  9. const commonObjectTracing = require('./utils/commonObjectTracing.js');
  10. const responseEnd = require('./utils/responseEnd.js');
  11. /**
  12. * Wraps an `app` directory server component with Sentry error instrumentation.
  13. */
  14. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  15. function wrapServerComponentWithSentry(
  16. appDirComponent,
  17. context,
  18. ) {
  19. core.addTracingExtensions();
  20. const { componentRoute, componentType } = context;
  21. // Even though users may define server components as async functions, for the client bundles
  22. // Next.js will turn them into synchronous functions and it will transform any `await`s into instances of the `use`
  23. // hook. 🤯
  24. return new Proxy(appDirComponent, {
  25. apply: (originalFunction, thisArg, args) => {
  26. // 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.
  27. return core.withIsolationScope(isolationScope => {
  28. const completeHeadersDict = context.headers
  29. ? utils.winterCGHeadersToDict(context.headers)
  30. : {};
  31. isolationScope.setSDKProcessingMetadata({
  32. request: {
  33. headers: completeHeadersDict,
  34. },
  35. });
  36. const incomingPropagationContext = utils.propagationContextFromHeaders(
  37. // eslint-disable-next-line deprecation/deprecation
  38. _nullishCoalesce(context.sentryTraceHeader, () => ( completeHeadersDict['sentry-trace'])),
  39. // eslint-disable-next-line deprecation/deprecation
  40. _nullishCoalesce(context.baggageHeader, () => ( completeHeadersDict['baggage'])),
  41. );
  42. const propagationContext = commonObjectTracing.commonObjectToPropagationContext(context.headers, incomingPropagationContext);
  43. isolationScope.setPropagationContext(propagationContext);
  44. core.getCurrentScope().setPropagationContext(propagationContext);
  45. return core.startSpanManual(
  46. {
  47. op: 'function.nextjs',
  48. name: `${componentType} Server Component (${componentRoute})`,
  49. attributes: {
  50. [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component',
  51. [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.nextjs',
  52. },
  53. },
  54. span => {
  55. return core.handleCallbackErrors(
  56. () => originalFunction.apply(thisArg, args),
  57. error => {
  58. if (nextNavigationErrorUtils.isNotFoundNavigationError(error)) {
  59. // We don't want to report "not-found"s
  60. _optionalChain([span, 'optionalAccess', _ => _.setStatus, 'call', _2 => _2('not_found')]);
  61. } else if (nextNavigationErrorUtils.isRedirectNavigationError(error)) {
  62. // We don't want to report redirects
  63. _optionalChain([span, 'optionalAccess', _3 => _3.setStatus, 'call', _4 => _4('ok')]);
  64. } else {
  65. _optionalChain([span, 'optionalAccess', _5 => _5.setStatus, 'call', _6 => _6('internal_error')]);
  66. core.captureException(error, {
  67. mechanism: {
  68. handled: false,
  69. },
  70. });
  71. }
  72. },
  73. () => {
  74. _optionalChain([span, 'optionalAccess', _7 => _7.end, 'call', _8 => _8()]);
  75. // flushQueue should not throw
  76. // eslint-disable-next-line @typescript-eslint/no-floating-promises
  77. responseEnd.flushQueue();
  78. },
  79. );
  80. },
  81. );
  82. });
  83. },
  84. });
  85. }
  86. exports.wrapServerComponentWithSentry = wrapServerComponentWithSentry;
  87. //# sourceMappingURL=wrapServerComponentWithSentry.js.map