@sentry/react-router 10.53.1 → 10.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/build/cjs/client/createClientInstrumentation.js +104 -175
  2. package/build/cjs/client/createClientInstrumentation.js.map +1 -1
  3. package/build/cjs/client/hydratedRouter.js +27 -74
  4. package/build/cjs/client/hydratedRouter.js.map +1 -1
  5. package/build/cjs/client/sdk.js +5 -16
  6. package/build/cjs/client/sdk.js.map +1 -1
  7. package/build/cjs/client/sentryOnError.js +4 -27
  8. package/build/cjs/client/sentryOnError.js.map +1 -1
  9. package/build/cjs/client/tracingIntegration.js +4 -18
  10. package/build/cjs/client/tracingIntegration.js.map +1 -1
  11. package/build/cjs/client/utils.js +5 -17
  12. package/build/cjs/client/utils.js.map +1 -1
  13. package/build/cjs/cloudflare/index.js +2 -15
  14. package/build/cjs/cloudflare/index.js.map +1 -1
  15. package/build/cjs/common/debug-build.js +0 -5
  16. package/build/cjs/common/debug-build.js.map +1 -1
  17. package/build/cjs/common/utils.js +8 -33
  18. package/build/cjs/common/utils.js.map +1 -1
  19. package/build/cjs/server/createSentryHandleError.js +4 -13
  20. package/build/cjs/server/createSentryHandleError.js.map +1 -1
  21. package/build/cjs/server/createSentryHandleRequest.js +14 -49
  22. package/build/cjs/server/createSentryHandleRequest.js.map +1 -1
  23. package/build/cjs/server/createServerInstrumentation.js +76 -114
  24. package/build/cjs/server/createServerInstrumentation.js.map +1 -1
  25. package/build/cjs/server/getMetaTagTransformer.js +2 -8
  26. package/build/cjs/server/getMetaTagTransformer.js.map +1 -1
  27. package/build/cjs/server/instrumentation/reactRouter.js +21 -47
  28. package/build/cjs/server/instrumentation/reactRouter.js.map +1 -1
  29. package/build/cjs/server/instrumentation/util.js +5 -41
  30. package/build/cjs/server/instrumentation/util.js.map +1 -1
  31. package/build/cjs/server/integration/lowQualityTransactionsFilterIntegration.js +5 -12
  32. package/build/cjs/server/integration/lowQualityTransactionsFilterIntegration.js.map +1 -1
  33. package/build/cjs/server/integration/reactRouterServer.js +10 -42
  34. package/build/cjs/server/integration/reactRouterServer.js.map +1 -1
  35. package/build/cjs/server/sdk.js +6 -20
  36. package/build/cjs/server/sdk.js.map +1 -1
  37. package/build/cjs/server/serverBuild.js +6 -31
  38. package/build/cjs/server/serverBuild.js.map +1 -1
  39. package/build/cjs/server/serverGlobals.js +6 -26
  40. package/build/cjs/server/serverGlobals.js.map +1 -1
  41. package/build/cjs/server/wrapSentryHandleRequest.js +13 -53
  42. package/build/cjs/server/wrapSentryHandleRequest.js.map +1 -1
  43. package/build/cjs/server/wrapServerAction.js +12 -44
  44. package/build/cjs/server/wrapServerAction.js.map +1 -1
  45. package/build/cjs/server/wrapServerLoader.js +12 -44
  46. package/build/cjs/server/wrapServerLoader.js.map +1 -1
  47. package/build/cjs/vite/buildEnd/handleOnBuildEnd.js +38 -72
  48. package/build/cjs/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
  49. package/build/cjs/vite/makeConfigInjectorPlugin.js +4 -12
  50. package/build/cjs/vite/makeConfigInjectorPlugin.js.map +1 -1
  51. package/build/cjs/vite/makeCustomSentryVitePlugins.js +10 -15
  52. package/build/cjs/vite/makeCustomSentryVitePlugins.js.map +1 -1
  53. package/build/cjs/vite/makeEnableSourceMapsPlugin.js +19 -51
  54. package/build/cjs/vite/makeEnableSourceMapsPlugin.js.map +1 -1
  55. package/build/cjs/vite/makeServerBuildCapturePlugin.js +4 -15
  56. package/build/cjs/vite/makeServerBuildCapturePlugin.js.map +1 -1
  57. package/build/cjs/vite/plugin.js +3 -16
  58. package/build/cjs/vite/plugin.js.map +1 -1
  59. package/build/esm/client/createClientInstrumentation.js +104 -175
  60. package/build/esm/client/createClientInstrumentation.js.map +1 -1
  61. package/build/esm/client/hydratedRouter.js +27 -74
  62. package/build/esm/client/hydratedRouter.js.map +1 -1
  63. package/build/esm/client/sdk.js +5 -16
  64. package/build/esm/client/sdk.js.map +1 -1
  65. package/build/esm/client/sentryOnError.js +4 -27
  66. package/build/esm/client/sentryOnError.js.map +1 -1
  67. package/build/esm/client/tracingIntegration.js +4 -18
  68. package/build/esm/client/tracingIntegration.js.map +1 -1
  69. package/build/esm/client/utils.js +5 -17
  70. package/build/esm/client/utils.js.map +1 -1
  71. package/build/esm/cloudflare/index.js +2 -15
  72. package/build/esm/cloudflare/index.js.map +1 -1
  73. package/build/esm/common/debug-build.js +0 -5
  74. package/build/esm/common/debug-build.js.map +1 -1
  75. package/build/esm/common/utils.js +8 -33
  76. package/build/esm/common/utils.js.map +1 -1
  77. package/build/esm/package.json +1 -1
  78. package/build/esm/server/createSentryHandleError.js +4 -13
  79. package/build/esm/server/createSentryHandleError.js.map +1 -1
  80. package/build/esm/server/createSentryHandleRequest.js +14 -49
  81. package/build/esm/server/createSentryHandleRequest.js.map +1 -1
  82. package/build/esm/server/createServerInstrumentation.js +76 -114
  83. package/build/esm/server/createServerInstrumentation.js.map +1 -1
  84. package/build/esm/server/getMetaTagTransformer.js +2 -8
  85. package/build/esm/server/getMetaTagTransformer.js.map +1 -1
  86. package/build/esm/server/instrumentation/reactRouter.js +21 -47
  87. package/build/esm/server/instrumentation/reactRouter.js.map +1 -1
  88. package/build/esm/server/instrumentation/util.js +5 -41
  89. package/build/esm/server/instrumentation/util.js.map +1 -1
  90. package/build/esm/server/integration/lowQualityTransactionsFilterIntegration.js +5 -12
  91. package/build/esm/server/integration/lowQualityTransactionsFilterIntegration.js.map +1 -1
  92. package/build/esm/server/integration/reactRouterServer.js +10 -42
  93. package/build/esm/server/integration/reactRouterServer.js.map +1 -1
  94. package/build/esm/server/sdk.js +6 -20
  95. package/build/esm/server/sdk.js.map +1 -1
  96. package/build/esm/server/serverBuild.js +6 -31
  97. package/build/esm/server/serverBuild.js.map +1 -1
  98. package/build/esm/server/serverGlobals.js +6 -26
  99. package/build/esm/server/serverGlobals.js.map +1 -1
  100. package/build/esm/server/wrapSentryHandleRequest.js +13 -53
  101. package/build/esm/server/wrapSentryHandleRequest.js.map +1 -1
  102. package/build/esm/server/wrapServerAction.js +12 -44
  103. package/build/esm/server/wrapServerAction.js.map +1 -1
  104. package/build/esm/server/wrapServerLoader.js +12 -44
  105. package/build/esm/server/wrapServerLoader.js.map +1 -1
  106. package/build/esm/vite/buildEnd/handleOnBuildEnd.js +38 -72
  107. package/build/esm/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
  108. package/build/esm/vite/makeConfigInjectorPlugin.js +4 -12
  109. package/build/esm/vite/makeConfigInjectorPlugin.js.map +1 -1
  110. package/build/esm/vite/makeCustomSentryVitePlugins.js +10 -15
  111. package/build/esm/vite/makeCustomSentryVitePlugins.js.map +1 -1
  112. package/build/esm/vite/makeEnableSourceMapsPlugin.js +19 -51
  113. package/build/esm/vite/makeEnableSourceMapsPlugin.js.map +1 -1
  114. package/build/esm/vite/makeServerBuildCapturePlugin.js +4 -15
  115. package/build/esm/vite/makeServerBuildCapturePlugin.js.map +1 -1
  116. package/build/esm/vite/plugin.js +3 -16
  117. package/build/esm/vite/plugin.js.map +1 -1
  118. package/build/types/client/hydratedRouter.d.ts.map +1 -1
  119. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../src/common/utils.ts"],"sourcesContent":["import { captureException, debug } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport type { InstrumentationResult } from './types';\n\n/**\n * Extracts pathname from request URL.\n * Falls back to '<unknown>' with DEBUG warning if URL cannot be parsed.\n */\nexport function getPathFromRequest(request: { url: string }): string {\n try {\n return new URL(request.url).pathname;\n } catch {\n try {\n // Fallback: use a dummy base URL since we only care about the pathname\n return new URL(request.url, 'http://example.com').pathname;\n } catch (error) {\n DEBUG_BUILD && debug.warn('Failed to parse URL from request:', request.url, error);\n return '<unknown>';\n }\n }\n}\n\n/**\n * Extracts route pattern from instrumentation info.\n * Prefers `pattern` (planned for v8) over `unstable_pattern` (v7.x).\n */\nexport function getPattern(info: { pattern?: string; unstable_pattern?: string }): string | undefined {\n return info.pattern ?? info.unstable_pattern;\n}\n\n/**\n * Normalizes route path by ensuring it starts with a slash.\n * Returns undefined if the input is falsy.\n */\nexport function normalizeRoutePath(pattern?: string): string | undefined {\n if (!pattern) {\n return undefined;\n }\n return pattern.startsWith('/') ? pattern : `/${pattern}`;\n}\n\n/**\n * Captures an error from instrumentation result.\n * Caller must verify result contains an Error before calling.\n */\nexport function captureInstrumentationError(\n result: InstrumentationResult,\n captureErrors: boolean,\n mechanismType: string,\n data: Record<string, string | boolean>,\n): void {\n if (captureErrors) {\n captureException(result.error, {\n mechanism: {\n type: mechanismType,\n handled: false,\n data,\n },\n });\n }\n}\n"],"names":[],"mappings":";;;AAIA;AACA;AACA;AACA;AACO,SAAS,kBAAkB,CAAC,OAAO,EAA2B;AACrE,EAAE,IAAI;AACN,IAAI,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ;AACxC,EAAE,EAAE,MAAM;AACV,IAAI,IAAI;AACR;AACA,MAAM,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC,QAAQ;AAChE,IAAI,CAAA,CAAE,OAAO,KAAK,EAAE;AACpB,MAAM,WAAA,IAAe,KAAK,CAAC,IAAI,CAAC,mCAAmC,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC;AACxF,MAAM,OAAO,WAAW;AACxB,IAAI;AACJ,EAAE;AACF;;AAEA;AACA;AACA;AACA;AACO,SAAS,UAAU,CAAC,IAAI,EAAuE;AACtG,EAAE,OAAO,IAAI,CAAC,WAAW,IAAI,CAAC,gBAAgB;AAC9C;;AAEA;AACA;AACA;AACA;AACO,SAAS,kBAAkB,CAAC,OAAO,EAA+B;AACzE,EAAE,IAAI,CAAC,OAAO,EAAE;AAChB,IAAI,OAAO,SAAS;AACpB,EAAE;AACF,EAAE,OAAO,OAAO,CAAC,UAAU,CAAC,GAAG,CAAA,GAAI,OAAA,GAAU,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAA,2BAAA;AACA,EAAA,MAAA;AACA,EAAA,aAAA;AACA,EAAA,aAAA;AACA,EAAA,IAAA;AACA,EAAA;AACA,EAAA,IAAA,aAAA,EAAA;AACA,IAAA,gBAAA,CAAA,MAAA,CAAA,KAAA,EAAA;AACA,MAAA,SAAA,EAAA;AACA,QAAA,IAAA,EAAA,aAAA;AACA,QAAA,OAAA,EAAA,KAAA;AACA,QAAA,IAAA;AACA,OAAA;AACA,KAAA,CAAA;AACA,EAAA;AACA;;;;"}
1
+ {"version":3,"file":"utils.js","sources":["../../../src/common/utils.ts"],"sourcesContent":["import { captureException, debug } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport type { InstrumentationResult } from './types';\n\n/**\n * Extracts pathname from request URL.\n * Falls back to '<unknown>' with DEBUG warning if URL cannot be parsed.\n */\nexport function getPathFromRequest(request: { url: string }): string {\n try {\n return new URL(request.url).pathname;\n } catch {\n try {\n // Fallback: use a dummy base URL since we only care about the pathname\n return new URL(request.url, 'http://example.com').pathname;\n } catch (error) {\n DEBUG_BUILD && debug.warn('Failed to parse URL from request:', request.url, error);\n return '<unknown>';\n }\n }\n}\n\n/**\n * Extracts route pattern from instrumentation info.\n * Prefers `pattern` (planned for v8) over `unstable_pattern` (v7.x).\n */\nexport function getPattern(info: { pattern?: string; unstable_pattern?: string }): string | undefined {\n return info.pattern ?? info.unstable_pattern;\n}\n\n/**\n * Normalizes route path by ensuring it starts with a slash.\n * Returns undefined if the input is falsy.\n */\nexport function normalizeRoutePath(pattern?: string): string | undefined {\n if (!pattern) {\n return undefined;\n }\n return pattern.startsWith('/') ? pattern : `/${pattern}`;\n}\n\n/**\n * Captures an error from instrumentation result.\n * Caller must verify result contains an Error before calling.\n */\nexport function captureInstrumentationError(\n result: InstrumentationResult,\n captureErrors: boolean,\n mechanismType: string,\n data: Record<string, string | boolean>,\n): void {\n if (captureErrors) {\n captureException(result.error, {\n mechanism: {\n type: mechanismType,\n handled: false,\n data,\n },\n });\n }\n}\n"],"names":[],"mappings":";;;AAQO,SAAS,mBAAmB,OAAA,EAAkC;AACnE,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA,CAAE,QAAA;AAAA,EAC9B,CAAA,CAAA,MAAQ;AACN,IAAA,IAAI;AAEF,MAAA,OAAO,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,EAAK,oBAAoB,CAAA,CAAE,QAAA;AAAA,IACpD,SAAS,KAAA,EAAO;AACd,MAAA,WAAA,IAAe,KAAA,CAAM,IAAA,CAAK,mCAAA,EAAqC,OAAA,CAAQ,KAAK,KAAK,CAAA;AACjF,MAAA,OAAO,WAAA;AAAA,IACT;AAAA,EACF;AACF;AAMO,SAAS,WAAW,IAAA,EAA2E;AACpG,EAAA,OAAO,IAAA,CAAK,WAAW,IAAA,CAAK,gBAAA;AAC9B;AAMO,SAAS,mBAAmB,OAAA,EAAsC;AACvE,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,QAAQ,UAAA,CAAW,GAAG,CAAA,GAAI,OAAA,GAAU,IAAI,OAAO,CAAA,CAAA;AACxD;AAMO,SAAS,2BAAA,CACd,MAAA,EACA,aAAA,EACA,aAAA,EACA,IAAA,EACM;AACN,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA,gBAAA,CAAiB,OAAO,KAAA,EAAO;AAAA,MAC7B,SAAA,EAAW;AAAA,QACT,IAAA,EAAM,aAAA;AAAA,QACN,OAAA,EAAS,KAAA;AAAA,QACT;AAAA;AACF,KACD,CAAA;AAAA,EACH;AACF;;;;"}
@@ -1 +1 @@
1
- {"type":"module","version":"10.53.1"}
1
+ {"type":"module","version":"10.54.0"}
@@ -1,32 +1,23 @@
1
1
  import { captureException, flushIfServerless } from '@sentry/core';
2
2
 
3
- /**
4
- * A complete Sentry-instrumented handleError implementation that handles error reporting
5
- *
6
- * @returns A Sentry-instrumented handleError function
7
- */
8
3
  function createSentryHandleError({ logErrors = false }) {
9
- const handleError = async function handleError(error, args) {
10
- // React Router may abort some interrupted requests, don't report those
4
+ const handleError = async function handleError2(error, args) {
11
5
  if (!args.request.signal.aborted) {
12
6
  captureException(error, {
13
7
  mechanism: {
14
- type: 'react-router',
15
- handled: false,
16
- },
8
+ type: "react-router",
9
+ handled: false
10
+ }
17
11
  });
18
12
  if (logErrors) {
19
- // eslint-disable-next-line no-console
20
13
  console.error(error);
21
14
  }
22
15
  try {
23
16
  await flushIfServerless();
24
17
  } catch {
25
- // Ignore flush errors to ensure error handling completes gracefully
26
18
  }
27
19
  }
28
20
  };
29
-
30
21
  return handleError;
31
22
  }
32
23
 
@@ -1 +1 @@
1
- {"version":3,"file":"createSentryHandleError.js","sources":["../../../src/server/createSentryHandleError.ts"],"sourcesContent":["import { captureException, flushIfServerless } from '@sentry/core';\nimport type { HandleErrorFunction } from 'react-router';\n\nexport type SentryHandleErrorOptions = {\n logErrors?: boolean;\n};\n\n/**\n * A complete Sentry-instrumented handleError implementation that handles error reporting\n *\n * @returns A Sentry-instrumented handleError function\n */\nexport function createSentryHandleError({ logErrors = false }: SentryHandleErrorOptions): HandleErrorFunction {\n const handleError: HandleErrorFunction = async function handleError(error, args): Promise<void> {\n // React Router may abort some interrupted requests, don't report those\n if (!args.request.signal.aborted) {\n captureException(error, {\n mechanism: {\n type: 'react-router',\n handled: false,\n },\n });\n if (logErrors) {\n // eslint-disable-next-line no-console\n console.error(error);\n }\n try {\n await flushIfServerless();\n } catch {\n // Ignore flush errors to ensure error handling completes gracefully\n }\n }\n };\n\n return handleError;\n}\n"],"names":[],"mappings":";;AAOA;AACA;AACA;AACA;AACA;AACO,SAAS,uBAAuB,CAAC,EAAE,YAAY,KAAA,EAAO,EAAiD;AAC9G,EAAE,MAAM,WAAW,GAAwB,eAAe,WAAW,CAAC,KAAK,EAAE,IAAI,EAAiB;AAClG;AACA,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE;AACtC,MAAM,gBAAgB,CAAC,KAAK,EAAE;AAC9B,QAAQ,SAAS,EAAE;AACnB,UAAU,IAAI,EAAE,cAAc;AAC9B,UAAU,OAAO,EAAE,KAAK;AACxB,SAAS;AACT,OAAO,CAAC;AACR,MAAM,IAAI,SAAS,EAAE;AACrB;AACA,QAAQ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;AAC5B,MAAM;AACN,MAAM,IAAI;AACV,QAAQ,MAAM,iBAAiB,EAAE;AACjC,MAAM,EAAE,MAAM;AACd;AACA,MAAM;AACN,IAAI;AACJ,EAAE,CAAC;;AAEH,EAAE,OAAO,WAAW;AACpB;;;;"}
1
+ {"version":3,"file":"createSentryHandleError.js","sources":["../../../src/server/createSentryHandleError.ts"],"sourcesContent":["import { captureException, flushIfServerless } from '@sentry/core';\nimport type { HandleErrorFunction } from 'react-router';\n\nexport type SentryHandleErrorOptions = {\n logErrors?: boolean;\n};\n\n/**\n * A complete Sentry-instrumented handleError implementation that handles error reporting\n *\n * @returns A Sentry-instrumented handleError function\n */\nexport function createSentryHandleError({ logErrors = false }: SentryHandleErrorOptions): HandleErrorFunction {\n const handleError: HandleErrorFunction = async function handleError(error, args): Promise<void> {\n // React Router may abort some interrupted requests, don't report those\n if (!args.request.signal.aborted) {\n captureException(error, {\n mechanism: {\n type: 'react-router',\n handled: false,\n },\n });\n if (logErrors) {\n // eslint-disable-next-line no-console\n console.error(error);\n }\n try {\n await flushIfServerless();\n } catch {\n // Ignore flush errors to ensure error handling completes gracefully\n }\n }\n };\n\n return handleError;\n}\n"],"names":["handleError"],"mappings":";;AAYO,SAAS,uBAAA,CAAwB,EAAE,SAAA,GAAY,KAAA,EAAM,EAAkD;AAC5G,EAAA,MAAM,WAAA,GAAmC,eAAeA,YAAAA,CAAY,KAAA,EAAO,IAAA,EAAqB;AAE9F,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,OAAA,EAAS;AAChC,MAAA,gBAAA,CAAiB,KAAA,EAAO;AAAA,QACtB,SAAA,EAAW;AAAA,UACT,IAAA,EAAM,cAAA;AAAA,UACN,OAAA,EAAS;AAAA;AACX,OACD,CAAA;AACD,MAAA,IAAI,SAAA,EAAW;AAEb,QAAA,OAAA,CAAQ,MAAM,KAAK,CAAA;AAAA,MACrB;AACA,MAAA,IAAI;AACF,QAAA,MAAM,iBAAA,EAAkB;AAAA,MAC1B,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,WAAA;AACT;;;;"}
@@ -3,84 +3,49 @@ import { PassThrough } from 'stream';
3
3
  import { getMetaTagTransformer } from './getMetaTagTransformer.js';
4
4
  import { wrapSentryHandleRequest } from './wrapSentryHandleRequest.js';
5
5
 
6
- /**
7
- * A complete Sentry-instrumented handleRequest implementation that handles both
8
- * route parametrization and trace meta tag injection.
9
- *
10
- * @param options Configuration options
11
- * @returns A Sentry-instrumented handleRequest function
12
- */
13
- function createSentryHandleRequest(
14
- options,
15
- ) {
6
+ function createSentryHandleRequest(options) {
16
7
  const {
17
- streamTimeout = 10000,
8
+ streamTimeout = 1e4,
18
9
  renderToPipeableStream,
19
10
  ServerRouter,
20
11
  createReadableStreamFromReadable,
21
- botRegex = /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i,
12
+ botRegex = /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i
22
13
  } = options;
23
-
24
- const handleRequest = function handleRequest(
25
- request,
26
- responseStatusCode,
27
- responseHeaders,
28
- routerContext,
29
- _loadContext,
30
- ) {
14
+ const handleRequest = function handleRequest2(request, responseStatusCode, responseHeaders, routerContext, _loadContext) {
31
15
  return new Promise((resolve, reject) => {
32
16
  let shellRendered = false;
33
- const userAgent = request.headers.get('user-agent');
34
-
35
- // Determine if we should use onAllReady or onShellReady
36
- const isBot = typeof userAgent === 'string' && botRegex.test(userAgent);
37
- const isSpaMode = !!(routerContext ).isSpaMode;
38
-
39
- const readyOption = isBot || isSpaMode ? 'onAllReady' : 'onShellReady';
40
-
41
- const { pipe, abort } = renderToPipeableStream(React.createElement(ServerRouter, { context: routerContext, url: request.url,} ), {
17
+ const userAgent = request.headers.get("user-agent");
18
+ const isBot = typeof userAgent === "string" && botRegex.test(userAgent);
19
+ const isSpaMode = !!routerContext.isSpaMode;
20
+ const readyOption = isBot || isSpaMode ? "onAllReady" : "onShellReady";
21
+ const { pipe, abort } = renderToPipeableStream(/* @__PURE__ */ React.createElement(ServerRouter, { context: routerContext, url: request.url }), {
42
22
  [readyOption]() {
43
23
  shellRendered = true;
44
24
  const body = new PassThrough();
45
-
46
25
  const stream = createReadableStreamFromReadable(body);
47
-
48
- responseHeaders.set('Content-Type', 'text/html');
49
-
26
+ responseHeaders.set("Content-Type", "text/html");
50
27
  resolve(
51
28
  new Response(stream, {
52
29
  headers: responseHeaders,
53
- status: responseStatusCode,
54
- }),
30
+ status: responseStatusCode
31
+ })
55
32
  );
56
-
57
- // this injects trace data to the HTML head
58
33
  pipe(getMetaTagTransformer(body));
59
34
  },
60
35
  onShellError(error) {
61
36
  reject(error);
62
37
  },
63
38
  onError(error) {
64
- // eslint-disable-next-line no-param-reassign
65
39
  responseStatusCode = 500;
66
- // Log streaming rendering errors from inside the shell. Don't log
67
- // errors encountered during initial shell rendering since they'll
68
- // reject and get logged in handleDocumentRequest.
69
40
  if (shellRendered) {
70
- // eslint-disable-next-line no-console
71
41
  console.error(error);
72
42
  }
73
- },
43
+ }
74
44
  });
75
-
76
- // Abort the rendering stream after the `streamTimeout`
77
45
  setTimeout(abort, streamTimeout);
78
46
  });
79
47
  };
80
-
81
- // Wrap the handle request function for request parametrization
82
- return wrapSentryHandleRequest(handleRequest )
83
- ;
48
+ return wrapSentryHandleRequest(handleRequest);
84
49
  }
85
50
 
86
51
  export { createSentryHandleRequest };
@@ -1 +1 @@
1
- {"version":3,"file":"createSentryHandleRequest.js","sources":["../../../src/server/createSentryHandleRequest.tsx"],"sourcesContent":["import type { createReadableStreamFromReadable } from '@react-router/node';\nimport type { ReactNode } from 'react';\nimport React from 'react';\nimport type { AppLoadContext, EntryContext, RouterContextProvider, ServerRouter } from 'react-router';\nimport { PassThrough } from 'stream';\nimport { getMetaTagTransformer } from './getMetaTagTransformer';\nimport { wrapSentryHandleRequest } from './wrapSentryHandleRequest';\n\ntype RenderToPipeableStreamOptions = {\n [key: string]: unknown;\n onShellReady?: () => void;\n onAllReady?: () => void;\n onShellError?: (error: unknown) => void;\n onError?: (error: unknown) => void;\n};\n\ntype RenderToPipeableStreamResult = {\n pipe: (destination: NodeJS.WritableStream) => void;\n abort: () => void;\n};\n\ntype RenderToPipeableStreamFunction = (\n node: ReactNode,\n options: RenderToPipeableStreamOptions,\n) => RenderToPipeableStreamResult;\n\nexport interface SentryHandleRequestOptions {\n /**\n * Timeout in milliseconds after which the rendering stream will be aborted\n * @default 10000\n */\n streamTimeout?: number;\n\n /**\n * React's renderToPipeableStream function from 'react-dom/server'\n */\n renderToPipeableStream: RenderToPipeableStreamFunction;\n\n /**\n * The <ServerRouter /> component from '@react-router/server'\n */\n ServerRouter: typeof ServerRouter;\n\n /**\n * createReadableStreamFromReadable from '@react-router/node'\n */\n createReadableStreamFromReadable: typeof createReadableStreamFromReadable;\n\n /**\n * Regular expression to identify bot user agents\n * @default /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i\n */\n botRegex?: RegExp;\n}\n\ntype HandleRequestWithoutMiddleware = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown>;\n\ntype HandleRequestWithMiddleware = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: RouterContextProvider,\n) => Promise<unknown>;\n\n/**\n * A complete Sentry-instrumented handleRequest implementation that handles both\n * route parametrization and trace meta tag injection.\n *\n * @param options Configuration options\n * @returns A Sentry-instrumented handleRequest function\n */\nexport function createSentryHandleRequest(\n options: SentryHandleRequestOptions,\n): HandleRequestWithoutMiddleware & HandleRequestWithMiddleware {\n const {\n streamTimeout = 10000,\n renderToPipeableStream,\n ServerRouter,\n createReadableStreamFromReadable,\n botRegex = /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i,\n } = options;\n\n const handleRequest = function handleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n _loadContext: AppLoadContext | RouterContextProvider,\n ): Promise<Response> {\n return new Promise((resolve, reject) => {\n let shellRendered = false;\n const userAgent = request.headers.get('user-agent');\n\n // Determine if we should use onAllReady or onShellReady\n const isBot = typeof userAgent === 'string' && botRegex.test(userAgent);\n const isSpaMode = !!(routerContext as { isSpaMode?: boolean }).isSpaMode;\n\n const readyOption = isBot || isSpaMode ? 'onAllReady' : 'onShellReady';\n\n const { pipe, abort } = renderToPipeableStream(<ServerRouter context={routerContext} url={request.url} />, {\n [readyOption]() {\n shellRendered = true;\n const body = new PassThrough();\n\n const stream = createReadableStreamFromReadable(body);\n\n responseHeaders.set('Content-Type', 'text/html');\n\n resolve(\n new Response(stream, {\n headers: responseHeaders,\n status: responseStatusCode,\n }),\n );\n\n // this injects trace data to the HTML head\n pipe(getMetaTagTransformer(body));\n },\n onShellError(error: unknown) {\n reject(error);\n },\n onError(error: unknown) {\n // eslint-disable-next-line no-param-reassign\n responseStatusCode = 500;\n // Log streaming rendering errors from inside the shell. Don't log\n // errors encountered during initial shell rendering since they'll\n // reject and get logged in handleDocumentRequest.\n if (shellRendered) {\n // eslint-disable-next-line no-console\n console.error(error);\n }\n },\n });\n\n // Abort the rendering stream after the `streamTimeout`\n setTimeout(abort, streamTimeout);\n });\n };\n\n // Wrap the handle request function for request parametrization\n return wrapSentryHandleRequest(handleRequest as HandleRequestWithoutMiddleware) as HandleRequestWithoutMiddleware &\n HandleRequestWithMiddleware;\n}\n"],"names":[],"mappings":";;;;;AAuEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,yBAAyB;AACzC,EAAE,OAAO;AACT,EAAgE;AAChE,EAAE,MAAM;AACR,IAAI,aAAA,GAAgB,KAAK;AACzB,IAAI,sBAAsB;AAC1B,IAAI,YAAY;AAChB,IAAI,gCAAgC;AACpC,IAAI,QAAA,GAAW,oFAAoF;AACnG,GAAE,GAAI,OAAO;;AAEb,EAAE,MAAM,aAAA,GAAgB,SAAS,aAAa;AAC9C,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,YAAY;AAChB,IAAuB;AACvB,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK;AAC5C,MAAM,IAAI,aAAA,GAAgB,KAAK;AAC/B,MAAM,MAAM,SAAA,GAAY,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;;AAEzD;AACA,MAAM,MAAM,KAAA,GAAQ,OAAO,SAAA,KAAc,QAAA,IAAY,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;AAC7E,MAAM,MAAM,YAAY,CAAC,CAAC,CAAC,aAAA,GAA0C,SAAS;;AAE9E,MAAM,MAAM,cAAc,KAAA,IAAS,SAAA,GAAY,YAAA,GAAe,cAAc;;AAE5E,MAAM,MAAM,EAAE,IAAI,EAAE,OAAM,GAAI,sBAAsB,CAAC,KAAA,CAAA,aAAA,CAAC,YAAA,EAAA,EAAa,OAAO,EAAC,aAAc,EAAE,GAAG,EAAC,OAAQ,CAAC,GAAG,EAAA,EAAI,EAAE;AACjH,QAAQ,CAAC,WAAW,CAAC,GAAG;AACxB,UAAU,aAAA,GAAgB,IAAI;AAC9B,UAAU,MAAM,IAAA,GAAO,IAAI,WAAW,EAAE;;AAExC,UAAU,MAAM,MAAA,GAAS,gCAAgC,CAAC,IAAI,CAAC;;AAE/D,UAAU,eAAe,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC;;AAE1D,UAAU,OAAO;AACjB,YAAY,IAAI,QAAQ,CAAC,MAAM,EAAE;AACjC,cAAc,OAAO,EAAE,eAAe;AACtC,cAAc,MAAM,EAAE,kBAAkB;AACxC,aAAa,CAAC;AACd,WAAW;;AAEX;AACA,UAAU,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;AAC3C,QAAQ,CAAC;AACT,QAAQ,YAAY,CAAC,KAAK,EAAW;AACrC,UAAU,MAAM,CAAC,KAAK,CAAC;AACvB,QAAQ,CAAC;AACT,QAAQ,OAAO,CAAC,KAAK,EAAW;AAChC;AACA,UAAU,kBAAA,GAAqB,GAAG;AAClC;AACA;AACA;AACA,UAAU,IAAI,aAAa,EAAE;AAC7B;AACA,YAAY,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;AAChC,UAAU;AACV,QAAQ,CAAC;AACT,OAAO,CAAC;;AAER;AACA,MAAM,UAAU,CAAC,KAAK,EAAE,aAAa,CAAC;AACtC,IAAI,CAAC,CAAC;AACN,EAAE,CAAC;;AAEH;AACA,EAAE,OAAO,uBAAuB,CAAC,aAAA;AAC7B;AACJ;;;;"}
1
+ {"version":3,"file":"createSentryHandleRequest.js","sources":["../../../src/server/createSentryHandleRequest.tsx"],"sourcesContent":["import type { createReadableStreamFromReadable } from '@react-router/node';\nimport type { ReactNode } from 'react';\nimport React from 'react';\nimport type { AppLoadContext, EntryContext, RouterContextProvider, ServerRouter } from 'react-router';\nimport { PassThrough } from 'stream';\nimport { getMetaTagTransformer } from './getMetaTagTransformer';\nimport { wrapSentryHandleRequest } from './wrapSentryHandleRequest';\n\ntype RenderToPipeableStreamOptions = {\n [key: string]: unknown;\n onShellReady?: () => void;\n onAllReady?: () => void;\n onShellError?: (error: unknown) => void;\n onError?: (error: unknown) => void;\n};\n\ntype RenderToPipeableStreamResult = {\n pipe: (destination: NodeJS.WritableStream) => void;\n abort: () => void;\n};\n\ntype RenderToPipeableStreamFunction = (\n node: ReactNode,\n options: RenderToPipeableStreamOptions,\n) => RenderToPipeableStreamResult;\n\nexport interface SentryHandleRequestOptions {\n /**\n * Timeout in milliseconds after which the rendering stream will be aborted\n * @default 10000\n */\n streamTimeout?: number;\n\n /**\n * React's renderToPipeableStream function from 'react-dom/server'\n */\n renderToPipeableStream: RenderToPipeableStreamFunction;\n\n /**\n * The <ServerRouter /> component from '@react-router/server'\n */\n ServerRouter: typeof ServerRouter;\n\n /**\n * createReadableStreamFromReadable from '@react-router/node'\n */\n createReadableStreamFromReadable: typeof createReadableStreamFromReadable;\n\n /**\n * Regular expression to identify bot user agents\n * @default /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i\n */\n botRegex?: RegExp;\n}\n\ntype HandleRequestWithoutMiddleware = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown>;\n\ntype HandleRequestWithMiddleware = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: RouterContextProvider,\n) => Promise<unknown>;\n\n/**\n * A complete Sentry-instrumented handleRequest implementation that handles both\n * route parametrization and trace meta tag injection.\n *\n * @param options Configuration options\n * @returns A Sentry-instrumented handleRequest function\n */\nexport function createSentryHandleRequest(\n options: SentryHandleRequestOptions,\n): HandleRequestWithoutMiddleware & HandleRequestWithMiddleware {\n const {\n streamTimeout = 10000,\n renderToPipeableStream,\n ServerRouter,\n createReadableStreamFromReadable,\n botRegex = /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i,\n } = options;\n\n const handleRequest = function handleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n _loadContext: AppLoadContext | RouterContextProvider,\n ): Promise<Response> {\n return new Promise((resolve, reject) => {\n let shellRendered = false;\n const userAgent = request.headers.get('user-agent');\n\n // Determine if we should use onAllReady or onShellReady\n const isBot = typeof userAgent === 'string' && botRegex.test(userAgent);\n const isSpaMode = !!(routerContext as { isSpaMode?: boolean }).isSpaMode;\n\n const readyOption = isBot || isSpaMode ? 'onAllReady' : 'onShellReady';\n\n const { pipe, abort } = renderToPipeableStream(<ServerRouter context={routerContext} url={request.url} />, {\n [readyOption]() {\n shellRendered = true;\n const body = new PassThrough();\n\n const stream = createReadableStreamFromReadable(body);\n\n responseHeaders.set('Content-Type', 'text/html');\n\n resolve(\n new Response(stream, {\n headers: responseHeaders,\n status: responseStatusCode,\n }),\n );\n\n // this injects trace data to the HTML head\n pipe(getMetaTagTransformer(body));\n },\n onShellError(error: unknown) {\n reject(error);\n },\n onError(error: unknown) {\n // eslint-disable-next-line no-param-reassign\n responseStatusCode = 500;\n // Log streaming rendering errors from inside the shell. Don't log\n // errors encountered during initial shell rendering since they'll\n // reject and get logged in handleDocumentRequest.\n if (shellRendered) {\n // eslint-disable-next-line no-console\n console.error(error);\n }\n },\n });\n\n // Abort the rendering stream after the `streamTimeout`\n setTimeout(abort, streamTimeout);\n });\n };\n\n // Wrap the handle request function for request parametrization\n return wrapSentryHandleRequest(handleRequest as HandleRequestWithoutMiddleware) as HandleRequestWithoutMiddleware &\n HandleRequestWithMiddleware;\n}\n"],"names":["handleRequest"],"mappings":";;;;;AA8EO,SAAS,0BACd,OAAA,EAC8D;AAC9D,EAAA,MAAM;AAAA,IACJ,aAAA,GAAgB,GAAA;AAAA,IAChB,sBAAA;AAAA,IACA,YAAA;AAAA,IACA,gCAAA;AAAA,IACA,QAAA,GAAW;AAAA,GACb,GAAI,OAAA;AAEJ,EAAA,MAAM,gBAAgB,SAASA,cAAAA,CAC7B,SACA,kBAAA,EACA,eAAA,EACA,eACA,YAAA,EACmB;AACnB,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,IAAI,aAAA,GAAgB,KAAA;AACpB,MAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,YAAY,CAAA;AAGlD,MAAA,MAAM,QAAQ,OAAO,SAAA,KAAc,QAAA,IAAY,QAAA,CAAS,KAAK,SAAS,CAAA;AACtE,MAAA,MAAM,SAAA,GAAY,CAAC,CAAE,aAAA,CAA0C,SAAA;AAE/D,MAAA,MAAM,WAAA,GAAc,KAAA,IAAS,SAAA,GAAY,YAAA,GAAe,cAAA;AAExD,MAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,sBAAA,iBAAuB,KAAA,CAAA,aAAA,CAAC,YAAA,EAAA,EAAa,OAAA,EAAS,aAAA,EAAe,GAAA,EAAK,OAAA,CAAQ,GAAA,EAAK,CAAA,EAAI;AAAA,QACzG,CAAC,WAAW,CAAA,GAAI;AACd,UAAA,aAAA,GAAgB,IAAA;AAChB,UAAA,MAAM,IAAA,GAAO,IAAI,WAAA,EAAY;AAE7B,UAAA,MAAM,MAAA,GAAS,iCAAiC,IAAI,CAAA;AAEpD,UAAA,eAAA,CAAgB,GAAA,CAAI,gBAAgB,WAAW,CAAA;AAE/C,UAAA,OAAA;AAAA,YACE,IAAI,SAAS,MAAA,EAAQ;AAAA,cACnB,OAAA,EAAS,eAAA;AAAA,cACT,MAAA,EAAQ;AAAA,aACT;AAAA,WACH;AAGA,UAAA,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAC,CAAA;AAAA,QAClC,CAAA;AAAA,QACA,aAAa,KAAA,EAAgB;AAC3B,UAAA,MAAA,CAAO,KAAK,CAAA;AAAA,QACd,CAAA;AAAA,QACA,QAAQ,KAAA,EAAgB;AAEtB,UAAA,kBAAA,GAAqB,GAAA;AAIrB,UAAA,IAAI,aAAA,EAAe;AAEjB,YAAA,OAAA,CAAQ,MAAM,KAAK,CAAA;AAAA,UACrB;AAAA,QACF;AAAA,OACD,CAAA;AAGD,MAAA,UAAA,CAAW,OAAO,aAAa,CAAA;AAAA,IACjC,CAAC,CAAA;AAAA,EACH,CAAA;AAGA,EAAA,OAAO,wBAAwB,aAA+C,CAAA;AAEhF;;;;"}
@@ -8,51 +8,35 @@ import { getMiddlewareName } from './serverBuild.js';
8
8
  import { markInstrumentationApiUsed } from './serverGlobals.js';
9
9
  export { isInstrumentationApiUsed } from './serverGlobals.js';
10
10
 
11
- const MIDDLEWARE_COUNTER_KEY = createContextKey('sentry_react_router_middleware_counter');
12
-
13
- /**
14
- * Options for creating Sentry server instrumentation.
15
- */
16
-
17
- /**
18
- * Creates a Sentry server instrumentation for React Router's instrumentation API.
19
- * @experimental
20
- */
21
- function createSentryServerInstrumentation(
22
- options = {},
23
- ) {
11
+ const MIDDLEWARE_COUNTER_KEY = createContextKey("sentry_react_router_middleware_counter");
12
+ function createSentryServerInstrumentation(options = {}) {
24
13
  const { captureErrors = true } = options;
25
-
26
14
  markInstrumentationApiUsed();
27
- DEBUG_BUILD && debug.log('React Router server instrumentation API enabled.');
28
-
15
+ DEBUG_BUILD && debug.log("React Router server instrumentation API enabled.");
29
16
  return {
30
17
  handler(handler) {
31
18
  handler.instrument({
32
19
  async request(handleRequest, info) {
33
20
  const pathname = getPathFromRequest(info.request);
34
21
  const activeSpan = getActiveSpan();
35
- const existingRootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;
36
-
37
- const counterStore = { counters: {} };
22
+ const existingRootSpan = activeSpan ? getRootSpan(activeSpan) : void 0;
23
+ const counterStore = { counters: {} };
38
24
  const ctx = context.active().setValue(MIDDLEWARE_COUNTER_KEY, counterStore);
39
-
40
25
  await context.with(ctx, async () => {
41
26
  if (existingRootSpan) {
42
27
  updateSpanName(existingRootSpan, `${info.request.method} ${pathname}`);
43
28
  existingRootSpan.setAttributes({
44
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',
45
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',
46
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
29
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
30
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.instrumentation_api",
31
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url"
47
32
  });
48
-
49
33
  try {
50
34
  const result = await handleRequest();
51
- if (result.status === 'error' && result.error instanceof Error) {
52
- existingRootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
53
- captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {
54
- 'http.method': info.request.method,
55
- 'http.url': pathname,
35
+ if (result.status === "error" && result.error instanceof Error) {
36
+ existingRootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
37
+ captureInstrumentationError(result, captureErrors, "react_router.request_handler", {
38
+ "http.method": info.request.method,
39
+ "http.url": pathname
56
40
  });
57
41
  }
58
42
  } finally {
@@ -64,188 +48,166 @@ function createSentryServerInstrumentation(
64
48
  name: `${info.request.method} ${pathname}`,
65
49
  forceTransaction: true,
66
50
  attributes: {
67
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',
68
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',
69
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
70
- 'http.request.method': info.request.method,
71
- 'url.path': pathname,
72
- 'url.full': info.request.url,
73
- },
51
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
52
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.instrumentation_api",
53
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
54
+ "http.request.method": info.request.method,
55
+ "url.path": pathname,
56
+ "url.full": info.request.url
57
+ }
74
58
  },
75
- async span => {
59
+ async (span) => {
76
60
  try {
77
61
  const result = await handleRequest();
78
- if (result.status === 'error' && result.error instanceof Error) {
79
- span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
80
- captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {
81
- 'http.method': info.request.method,
82
- 'http.url': pathname,
62
+ if (result.status === "error" && result.error instanceof Error) {
63
+ span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
64
+ captureInstrumentationError(result, captureErrors, "react_router.request_handler", {
65
+ "http.method": info.request.method,
66
+ "http.url": pathname
83
67
  });
84
68
  }
85
69
  } finally {
86
70
  await flushIfServerless();
87
71
  }
88
- },
72
+ }
89
73
  );
90
74
  }
91
75
  });
92
- },
76
+ }
93
77
  });
94
78
  },
95
-
96
79
  route(route) {
97
80
  const routeId = route.id;
98
-
99
81
  route.instrument({
100
82
  async loader(callLoader, info) {
101
83
  const urlPath = getPathFromRequest(info.request);
102
84
  const pattern = getPattern(info);
103
85
  const routePattern = normalizeRoutePath(pattern) || urlPath;
104
86
  updateRootSpanWithRoute(info.request.method, pattern, urlPath);
105
-
106
87
  await startSpan(
107
88
  {
108
89
  name: routePattern,
109
90
  attributes: {
110
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.loader',
111
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',
112
- },
91
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.loader",
92
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
93
+ }
113
94
  },
114
- async span => {
95
+ async (span) => {
115
96
  const result = await callLoader();
116
- if (result.status === 'error' && result.error instanceof Error) {
117
- span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
118
- captureInstrumentationError(result, captureErrors, 'react_router.loader', {
119
- 'http.method': info.request.method,
120
- 'http.url': urlPath,
97
+ if (result.status === "error" && result.error instanceof Error) {
98
+ span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
99
+ captureInstrumentationError(result, captureErrors, "react_router.loader", {
100
+ "http.method": info.request.method,
101
+ "http.url": urlPath
121
102
  });
122
103
  }
123
- },
104
+ }
124
105
  );
125
106
  },
126
-
127
107
  async action(callAction, info) {
128
108
  const urlPath = getPathFromRequest(info.request);
129
109
  const pattern = getPattern(info);
130
110
  const routePattern = normalizeRoutePath(pattern) || urlPath;
131
111
  updateRootSpanWithRoute(info.request.method, pattern, urlPath);
132
-
133
112
  await startSpan(
134
113
  {
135
114
  name: routePattern,
136
115
  attributes: {
137
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.action',
138
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',
139
- },
116
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.action",
117
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
118
+ }
140
119
  },
141
- async span => {
120
+ async (span) => {
142
121
  const result = await callAction();
143
- if (result.status === 'error' && result.error instanceof Error) {
144
- span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
145
- captureInstrumentationError(result, captureErrors, 'react_router.action', {
146
- 'http.method': info.request.method,
147
- 'http.url': urlPath,
122
+ if (result.status === "error" && result.error instanceof Error) {
123
+ span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
124
+ captureInstrumentationError(result, captureErrors, "react_router.action", {
125
+ "http.method": info.request.method,
126
+ "http.url": urlPath
148
127
  });
149
128
  }
150
- },
129
+ }
151
130
  );
152
131
  },
153
-
154
132
  async middleware(callMiddleware, info) {
155
133
  const urlPath = getPathFromRequest(info.request);
156
134
  const pattern = getPattern(info);
157
135
  const routePattern = normalizeRoutePath(pattern) || urlPath;
158
-
159
136
  updateRootSpanWithRoute(info.request.method, pattern, urlPath);
160
-
161
- const counterStore = context.active().getValue(MIDDLEWARE_COUNTER_KEY)
162
-
163
- ;
137
+ const counterStore = context.active().getValue(MIDDLEWARE_COUNTER_KEY);
164
138
  let middlewareIndex = 0;
165
139
  if (counterStore) {
166
140
  middlewareIndex = counterStore.counters[routeId] ?? 0;
167
141
  counterStore.counters[routeId] = middlewareIndex + 1;
168
142
  }
169
-
170
143
  const middlewareName = getMiddlewareName(routeId, middlewareIndex);
171
-
172
144
  await startSpan(
173
145
  {
174
146
  name: `middleware ${middlewareName || routeId}`,
175
147
  attributes: {
176
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.middleware',
177
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',
178
- 'react_router.route.id': routeId,
148
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.middleware",
149
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api",
150
+ "react_router.route.id": routeId,
179
151
  [ATTR_HTTP_ROUTE]: routePattern,
180
- ...(middlewareName && { 'react_router.middleware.name': middlewareName }),
181
- 'react_router.middleware.index': middlewareIndex,
182
- },
152
+ ...middlewareName && { "react_router.middleware.name": middlewareName },
153
+ "react_router.middleware.index": middlewareIndex
154
+ }
183
155
  },
184
- async span => {
156
+ async (span) => {
185
157
  const result = await callMiddleware();
186
- if (result.status === 'error' && result.error instanceof Error) {
187
- span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
188
- captureInstrumentationError(result, captureErrors, 'react_router.middleware', {
189
- 'http.method': info.request.method,
190
- 'http.url': urlPath,
158
+ if (result.status === "error" && result.error instanceof Error) {
159
+ span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
160
+ captureInstrumentationError(result, captureErrors, "react_router.middleware", {
161
+ "http.method": info.request.method,
162
+ "http.url": urlPath
191
163
  });
192
164
  }
193
- },
165
+ }
194
166
  );
195
167
  },
196
-
197
168
  async lazy(callLazy) {
198
169
  await startSpan(
199
170
  {
200
- name: 'Lazy Route Load',
171
+ name: "Lazy Route Load",
201
172
  attributes: {
202
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.lazy',
203
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',
204
- },
173
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.lazy",
174
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
175
+ }
205
176
  },
206
- async span => {
177
+ async (span) => {
207
178
  const result = await callLazy();
208
- if (result.status === 'error' && result.error instanceof Error) {
209
- span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
210
- captureInstrumentationError(result, captureErrors, 'react_router.lazy', {});
179
+ if (result.status === "error" && result.error instanceof Error) {
180
+ span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
181
+ captureInstrumentationError(result, captureErrors, "react_router.lazy", {});
211
182
  }
212
- },
183
+ }
213
184
  );
214
- },
185
+ }
215
186
  });
216
- },
187
+ }
217
188
  };
218
189
  }
219
-
220
190
  function updateRootSpanWithRoute(method, pattern, urlPath) {
221
191
  const activeSpan = getActiveSpan();
222
192
  if (!activeSpan) return;
223
193
  const rootSpan = getRootSpan(activeSpan);
224
194
  if (!rootSpan) return;
225
-
226
- // Skip update if URL path is invalid (failed to parse)
227
- if (!urlPath || urlPath === '<unknown>') {
228
- DEBUG_BUILD && debug.warn('Cannot update span with invalid URL path:', urlPath);
195
+ if (!urlPath || urlPath === "<unknown>") {
196
+ DEBUG_BUILD && debug.warn("Cannot update span with invalid URL path:", urlPath);
229
197
  return;
230
198
  }
231
-
232
199
  const hasPattern = !!pattern;
233
200
  const routeName = hasPattern ? normalizeRoutePath(pattern) || urlPath : urlPath;
234
-
235
201
  const rpcMetadata = getRPCMetadata(context.active());
236
202
  if (rpcMetadata?.type === RPCType.HTTP) {
237
203
  rpcMetadata.route = routeName;
238
204
  }
239
-
240
205
  const transactionName = `${method} ${routeName}`;
241
206
  updateSpanName(rootSpan, transactionName);
242
207
  rootSpan.setAttributes({
243
208
  [ATTR_HTTP_ROUTE]: routeName,
244
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: hasPattern ? 'route' : 'url',
209
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: hasPattern ? "route" : "url"
245
210
  });
246
-
247
- // Also update the scope's transaction name so errors captured during this request
248
- // have the correct transaction name (not the initial placeholder like "GET *")
249
211
  getCurrentScope().setTransactionName(transactionName);
250
212
  }
251
213