@sentry/react-router 10.70.0 → 11.0.0-alpha.1

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 (115) hide show
  1. package/build/cjs/client/createClientInstrumentation.js +20 -13
  2. package/build/cjs/client/createClientInstrumentation.js.map +1 -1
  3. package/build/cjs/client/hydratedRouter.js +10 -6
  4. package/build/cjs/client/hydratedRouter.js.map +1 -1
  5. package/build/cjs/client/tracingIntegration.js +1 -0
  6. package/build/cjs/client/tracingIntegration.js.map +1 -1
  7. package/build/cjs/client/utils.js +6 -2
  8. package/build/cjs/client/utils.js.map +1 -1
  9. package/build/cjs/index.server.js +0 -5
  10. package/build/cjs/index.server.js.map +1 -1
  11. package/build/cjs/server/createSentryHandleRequest.js.map +1 -1
  12. package/build/cjs/server/createServerInstrumentation.js +71 -65
  13. package/build/cjs/server/createServerInstrumentation.js.map +1 -1
  14. package/build/cjs/server/integration/lowQualityTransactionsFilterIntegration.js +1 -1
  15. package/build/cjs/server/integration/lowQualityTransactionsFilterIntegration.js.map +1 -1
  16. package/build/cjs/server/integration/reactRouterServer.js +1 -40
  17. package/build/cjs/server/integration/reactRouterServer.js.map +1 -1
  18. package/build/cjs/server/sdk.js +1 -1
  19. package/build/cjs/server/sdk.js.map +1 -1
  20. package/build/cjs/server/serverBuild.js +0 -4
  21. package/build/cjs/server/serverBuild.js.map +1 -1
  22. package/build/cjs/server/serverGlobals.js +0 -9
  23. package/build/cjs/server/serverGlobals.js.map +1 -1
  24. package/build/cjs/server/wrapSentryHandleRequest.js +0 -2
  25. package/build/cjs/server/wrapSentryHandleRequest.js.map +1 -1
  26. package/build/cjs/vite/buildEnd/handleOnBuildEnd.js +4 -14
  27. package/build/cjs/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
  28. package/build/cjs/vite/makeCustomSentryVitePlugins.js +2 -2
  29. package/build/cjs/vite/makeCustomSentryVitePlugins.js.map +1 -1
  30. package/build/cjs/vite/makeServerBuildCapturePlugin.js +2 -6
  31. package/build/cjs/vite/makeServerBuildCapturePlugin.js.map +1 -1
  32. package/build/cjs/vite/plugin.js +2 -0
  33. package/build/cjs/vite/plugin.js.map +1 -1
  34. package/build/esm/client/createClientInstrumentation.js +22 -15
  35. package/build/esm/client/createClientInstrumentation.js.map +1 -1
  36. package/build/esm/client/hydratedRouter.js +11 -7
  37. package/build/esm/client/hydratedRouter.js.map +1 -1
  38. package/build/esm/client/tracingIntegration.js +1 -0
  39. package/build/esm/client/tracingIntegration.js.map +1 -1
  40. package/build/esm/client/utils.js +7 -3
  41. package/build/esm/client/utils.js.map +1 -1
  42. package/build/esm/index.server.js +1 -3
  43. package/build/esm/index.server.js.map +1 -1
  44. package/build/esm/package.json +1 -1
  45. package/build/esm/server/createSentryHandleRequest.js.map +1 -1
  46. package/build/esm/server/createServerInstrumentation.js +73 -67
  47. package/build/esm/server/createServerInstrumentation.js.map +1 -1
  48. package/build/esm/server/integration/lowQualityTransactionsFilterIntegration.js +1 -1
  49. package/build/esm/server/integration/lowQualityTransactionsFilterIntegration.js.map +1 -1
  50. package/build/esm/server/integration/reactRouterServer.js +3 -41
  51. package/build/esm/server/integration/reactRouterServer.js.map +1 -1
  52. package/build/esm/server/sdk.js +1 -1
  53. package/build/esm/server/sdk.js.map +1 -1
  54. package/build/esm/server/serverBuild.js +1 -4
  55. package/build/esm/server/serverBuild.js.map +1 -1
  56. package/build/esm/server/serverGlobals.js +1 -8
  57. package/build/esm/server/serverGlobals.js.map +1 -1
  58. package/build/esm/server/wrapSentryHandleRequest.js +1 -2
  59. package/build/esm/server/wrapSentryHandleRequest.js.map +1 -1
  60. package/build/esm/vite/buildEnd/handleOnBuildEnd.js +4 -14
  61. package/build/esm/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
  62. package/build/esm/vite/makeCustomSentryVitePlugins.js +1 -1
  63. package/build/esm/vite/makeCustomSentryVitePlugins.js.map +1 -1
  64. package/build/esm/vite/makeServerBuildCapturePlugin.js +2 -6
  65. package/build/esm/vite/makeServerBuildCapturePlugin.js.map +1 -1
  66. package/build/esm/vite/plugin.js +2 -0
  67. package/build/esm/vite/plugin.js.map +1 -1
  68. package/build/types/client/createClientInstrumentation.d.ts.map +1 -1
  69. package/build/types/client/hydratedRouter.d.ts.map +1 -1
  70. package/build/types/client/tracingIntegration.d.ts.map +1 -1
  71. package/build/types/client/utils.d.ts.map +1 -1
  72. package/build/types/index.types.d.ts +1 -0
  73. package/build/types/index.types.d.ts.map +1 -1
  74. package/build/types/server/createSentryHandleRequest.d.ts.map +1 -1
  75. package/build/types/server/createServerInstrumentation.d.ts.map +1 -1
  76. package/build/types/server/index.d.ts +1 -3
  77. package/build/types/server/index.d.ts.map +1 -1
  78. package/build/types/server/integration/lowQualityTransactionsFilterIntegration.d.ts +1 -2
  79. package/build/types/server/integration/lowQualityTransactionsFilterIntegration.d.ts.map +1 -1
  80. package/build/types/server/integration/reactRouterServer.d.ts +0 -3
  81. package/build/types/server/integration/reactRouterServer.d.ts.map +1 -1
  82. package/build/types/server/serverGlobals.d.ts +0 -10
  83. package/build/types/server/serverGlobals.d.ts.map +1 -1
  84. package/build/types/server/wrapSentryHandleRequest.d.ts +0 -2
  85. package/build/types/server/wrapSentryHandleRequest.d.ts.map +1 -1
  86. package/build/types/vite/buildEnd/handleOnBuildEnd.d.ts.map +1 -1
  87. package/build/types/vite/makeServerBuildCapturePlugin.d.ts.map +1 -1
  88. package/build/types/vite/plugin.d.ts.map +1 -1
  89. package/build/types/vite/types.d.ts +1 -49
  90. package/build/types/vite/types.d.ts.map +1 -1
  91. package/package.json +15 -15
  92. package/build/cjs/server/instrumentation/reactRouter.js +0 -106
  93. package/build/cjs/server/instrumentation/reactRouter.js.map +0 -1
  94. package/build/cjs/server/instrumentation/util.js +0 -24
  95. package/build/cjs/server/instrumentation/util.js.map +0 -1
  96. package/build/cjs/server/wrapServerAction.js +0 -56
  97. package/build/cjs/server/wrapServerAction.js.map +0 -1
  98. package/build/cjs/server/wrapServerLoader.js +0 -56
  99. package/build/cjs/server/wrapServerLoader.js.map +0 -1
  100. package/build/esm/server/instrumentation/reactRouter.js +0 -104
  101. package/build/esm/server/instrumentation/reactRouter.js.map +0 -1
  102. package/build/esm/server/instrumentation/util.js +0 -18
  103. package/build/esm/server/instrumentation/util.js.map +0 -1
  104. package/build/esm/server/wrapServerAction.js +0 -54
  105. package/build/esm/server/wrapServerAction.js.map +0 -1
  106. package/build/esm/server/wrapServerLoader.js +0 -54
  107. package/build/esm/server/wrapServerLoader.js.map +0 -1
  108. package/build/types/server/instrumentation/reactRouter.d.ts +0 -19
  109. package/build/types/server/instrumentation/reactRouter.d.ts.map +0 -1
  110. package/build/types/server/instrumentation/util.d.ts +0 -31
  111. package/build/types/server/instrumentation/util.d.ts.map +0 -1
  112. package/build/types/server/wrapServerAction.d.ts +0 -33
  113. package/build/types/server/wrapServerAction.d.ts.map +0 -1
  114. package/build/types/server/wrapServerLoader.d.ts +0 -33
  115. package/build/types/server/wrapServerLoader.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../src/client/utils.ts"],"sourcesContent":["import { getAbsoluteUrl } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport { GLOBAL_OBJ, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';\nimport { URL_FULL, URL_PATH, URL_TEMPLATE } from '@sentry/conventions/attributes';\nimport type { DataRouter, RouterState } from 'react-router';\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\nconst GLOBAL_OBJ_WITH_DATA_ROUTER = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n __reactRouterDataRouter?: DataRouter;\n};\n\n/**\n * Resolves a navigate argument to a pathname string.\n *\n * React Router's navigate() accepts a string, number, or a To object ({ pathname, search, hash }).\n * All fields in the To object are optional (Partial<Path>), so we need to detect object args\n * to avoid \"[object Object]\" transaction names.\n */\nexport function resolveNavigateArg(target: unknown): string {\n if (typeof target !== 'object' || target === null) {\n // string or number\n return String(target);\n }\n\n // Object `to` with pathname\n const pathname = (target as Record<string, unknown>).pathname;\n if (typeof pathname === 'string') {\n return pathname || '/';\n }\n\n // Object `to` without pathname - navigation stays on current path\n return WINDOW.location?.pathname || '/';\n}\n\n/**\n * Resolves a navigate argument to the full destination path, preserving `search`/`hash` from a\n * To object. Unlike `resolveNavigateArg` (used for span/route naming, which should stay a bare\n * path), this is used to derive `url.full`/`url.path`, which should reflect the actual\n * destination the user is navigating to, including any query string.\n */\nexport function resolveNavigateUrl(target: unknown): string {\n if (typeof target !== 'object' || target === null) {\n // string or number\n return String(target);\n }\n\n const { pathname, search, hash } = target as Record<string, unknown>;\n const path = typeof pathname === 'string' && pathname !== '' ? pathname : WINDOW.location?.pathname || '/';\n\n return `${path}${typeof search === 'string' ? search : ''}${typeof hash === 'string' ? hash : ''}`;\n}\n\nfunction getNavigateBaseUrl(currentUrl?: string): string {\n const origin = WINDOW.location?.origin || 'http://localhost';\n\n // Prefer the live pathname, but fall back to the hook-provided `currentUrl` (which may be a full\n // URL or a bare path) when `location` is unavailable (e.g. SSR/non-browser environments).\n let pathname = WINDOW.location?.pathname;\n if (!pathname && currentUrl) {\n try {\n pathname = new URL(currentUrl, origin).pathname;\n } catch {\n pathname = currentUrl.startsWith('/') ? currentUrl : `/${currentUrl}`;\n }\n }\n pathname = pathname || '/';\n\n // React Router resolves relative navigate targets against the current path treated as a\n // *directory* (it appends segments), whereas the WHATWG `URL` parser treats the last path\n // segment as a file and drops it. Enforce a trailing slash so relative resolution matches\n // React Router, e.g. `navigate('ssr')` from `/performance` -> `/performance/ssr` (not `/ssr`).\n const directory = pathname.endsWith('/') ? pathname : `${pathname}/`;\n\n return `${origin}${directory}`;\n}\n\n/**\n * Resolves a navigate argument to an absolute URL for `url.full`/`url.path`, correctly handling\n * relative targets (no leading slash) by resolving them against the current URL instead of the\n * document origin alone.\n */\nexport function resolveNavigateAbsoluteUrl(target: unknown, currentUrl?: string): string {\n const destination = resolveNavigateUrl(target);\n\n try {\n const resolved = new URL(destination, getNavigateBaseUrl(currentUrl));\n return getAbsoluteUrl(`${resolved.pathname}${resolved.search}${resolved.hash}`);\n } catch {\n return getAbsoluteUrl(destination);\n }\n}\n\n/**\n * Updates a navigation span's name and `url.path`/`url.full` from the current `location`.\n */\nexport function updateNavigationSpanUrlFromLocation(span: Span): void {\n if (!WINDOW.location) {\n return;\n }\n\n const { pathname, search = '', hash = '' } = WINDOW.location;\n const destinationUrl = getAbsoluteUrl(`${pathname}${search}${hash}`);\n\n span.updateName(pathname);\n span.setAttributes({\n [URL_PATH]: pathname,\n [URL_FULL]: destinationUrl,\n });\n}\n\nexport function normalizePathname(pathname: string): string {\n let normalized = pathname.startsWith('/') ? pathname : `/${pathname}`;\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n return normalized;\n}\n\nexport function getParameterizedRoute(routerState: RouterState): string {\n const lastMatch = routerState.matches[routerState.matches.length - 1];\n return normalizePathname(lastMatch?.route.path || routerState.location.pathname);\n}\n\n/**\n * Updates a navigation span's URL attributes and parameterizes its name from the router state.\n * Used after numeric navigations (`navigate(-1)` / `navigate(1)`) where route hooks may not\n * supply a pattern (e.g. index routes).\n *\n * `url.path` reflects raw `location.pathname` (may include a trailing slash when the server\n * redirects index routes), while `url.template` is normalized without trailing slashes.\n */\nexport function finalizeNavigationSpanFromRouterState(span: Span, routerState: RouterState): void {\n updateNavigationSpanUrlFromLocation(span);\n\n if (!WINDOW.location) {\n return;\n }\n\n const { pathname } = WINDOW.location;\n\n if (\n routerState.navigation?.state === 'idle' &&\n normalizePathname(routerState.location.pathname) === normalizePathname(pathname)\n ) {\n const parameterizedRoute = getParameterizedRoute(routerState);\n span.updateName(parameterizedRoute);\n span.setAttributes({ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route', [URL_TEMPLATE]: parameterizedRoute });\n }\n}\n\n/**\n * Finalizes a navigation span after numeric navigation using the hydrated data router when\n * available, otherwise falls back to URL attributes from `location` alone.\n */\nexport function finalizeNavigationSpanFromHydratedRouter(span: Span): void {\n const router = GLOBAL_OBJ_WITH_DATA_ROUTER.__reactRouterDataRouter;\n if (router) {\n finalizeNavigationSpanFromRouterState(span, router.state);\n } else {\n updateNavigationSpanUrlFromLocation(span);\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../../../src/client/utils.ts"],"sourcesContent":["import { getAbsoluteUrl } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport { GLOBAL_OBJ, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, filterCollectedUrl } from '@sentry/core';\nimport { URL_FULL, URL_PATH, URL_TEMPLATE } from '@sentry/conventions/attributes';\nimport type { DataRouter, RouterState } from 'react-router';\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\nconst GLOBAL_OBJ_WITH_DATA_ROUTER = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n __reactRouterDataRouter?: DataRouter;\n};\n\n/**\n * Resolves a navigate argument to a pathname string.\n *\n * React Router's navigate() accepts a string, number, or a To object ({ pathname, search, hash }).\n * All fields in the To object are optional (Partial<Path>), so we need to detect object args\n * to avoid \"[object Object]\" transaction names.\n */\nexport function resolveNavigateArg(target: unknown): string {\n if (typeof target !== 'object' || target === null) {\n // string or number\n return String(target);\n }\n\n // Object `to` with pathname\n const pathname = (target as Record<string, unknown>).pathname;\n if (typeof pathname === 'string') {\n return pathname || '/';\n }\n\n // Object `to` without pathname - navigation stays on current path\n return WINDOW.location?.pathname || '/';\n}\n\n/**\n * Resolves a navigate argument to the full destination path, preserving `search`/`hash` from a\n * To object. Unlike `resolveNavigateArg` (used for span/route naming, which should stay a bare\n * path), this is used to derive `url.full`/`url.path`, which should reflect the actual\n * destination the user is navigating to, including any query string.\n */\nexport function resolveNavigateUrl(target: unknown): string {\n if (typeof target !== 'object' || target === null) {\n // string or number\n return String(target);\n }\n\n const { pathname, search, hash } = target as Record<string, unknown>;\n const path = typeof pathname === 'string' && pathname !== '' ? pathname : WINDOW.location?.pathname || '/';\n\n return `${path}${typeof search === 'string' ? search : ''}${typeof hash === 'string' ? hash : ''}`;\n}\n\nfunction getNavigateBaseUrl(currentUrl?: string): string {\n const origin = WINDOW.location?.origin || 'http://localhost';\n\n // Prefer the live pathname, but fall back to the hook-provided `currentUrl` (which may be a full\n // URL or a bare path) when `location` is unavailable (e.g. SSR/non-browser environments).\n let pathname = WINDOW.location?.pathname;\n if (!pathname && currentUrl) {\n try {\n pathname = new URL(currentUrl, origin).pathname;\n } catch {\n pathname = currentUrl.startsWith('/') ? currentUrl : `/${currentUrl}`;\n }\n }\n pathname = pathname || '/';\n\n // React Router resolves relative navigate targets against the current path treated as a\n // *directory* (it appends segments), whereas the WHATWG `URL` parser treats the last path\n // segment as a file and drops it. Enforce a trailing slash so relative resolution matches\n // React Router, e.g. `navigate('ssr')` from `/performance` -> `/performance/ssr` (not `/ssr`).\n const directory = pathname.endsWith('/') ? pathname : `${pathname}/`;\n\n return `${origin}${directory}`;\n}\n\n/**\n * Resolves a navigate argument to an absolute URL for `url.full`/`url.path`, correctly handling\n * relative targets (no leading slash) by resolving them against the current URL instead of the\n * document origin alone.\n */\nexport function resolveNavigateAbsoluteUrl(target: unknown, currentUrl?: string): string {\n const destination = resolveNavigateUrl(target);\n\n try {\n const resolved = new URL(destination, getNavigateBaseUrl(currentUrl));\n return getAbsoluteUrl(`${resolved.pathname}${resolved.search}${resolved.hash}`);\n } catch {\n return getAbsoluteUrl(destination);\n }\n}\n\n/**\n * Updates a navigation span's name and `url.path`/`url.full` from the current `location`.\n */\nexport function updateNavigationSpanUrlFromLocation(span: Span): void {\n if (!WINDOW.location) {\n return;\n }\n\n const { pathname, search = '', hash = '' } = WINDOW.location;\n const destinationUrl = getAbsoluteUrl(`${pathname}${search}${hash}`);\n\n span.updateName(pathname);\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [URL_PATH]: pathname,\n [URL_FULL]: filterCollectedUrl(destinationUrl),\n });\n}\n\nexport function normalizePathname(pathname: string): string {\n let normalized = pathname.startsWith('/') ? pathname : `/${pathname}`;\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n return normalized;\n}\n\nexport function getParameterizedRoute(routerState: RouterState): string {\n const lastMatch = routerState.matches[routerState.matches.length - 1];\n return normalizePathname(lastMatch?.route.path || routerState.location.pathname);\n}\n\n/**\n * Updates a navigation span's URL attributes and parameterizes its name from the router state.\n * Used after numeric navigations (`navigate(-1)` / `navigate(1)`) where route hooks may not\n * supply a pattern (e.g. index routes).\n *\n * `url.path` reflects raw `location.pathname` (may include a trailing slash when the server\n * redirects index routes), while `url.template` is normalized without trailing slashes.\n */\nexport function finalizeNavigationSpanFromRouterState(span: Span, routerState: RouterState): void {\n updateNavigationSpanUrlFromLocation(span);\n\n if (!WINDOW.location) {\n return;\n }\n\n const { pathname } = WINDOW.location;\n\n if (\n routerState.navigation?.state === 'idle' &&\n normalizePathname(routerState.location.pathname) === normalizePathname(pathname)\n ) {\n const parameterizedRoute = getParameterizedRoute(routerState);\n span.updateName(parameterizedRoute);\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [URL_TEMPLATE]: parameterizedRoute,\n });\n }\n}\n\n/**\n * Finalizes a navigation span after numeric navigation using the hydrated data router when\n * available, otherwise falls back to URL attributes from `location` alone.\n */\nexport function finalizeNavigationSpanFromHydratedRouter(span: Span): void {\n const router = GLOBAL_OBJ_WITH_DATA_ROUTER.__reactRouterDataRouter;\n if (router) {\n finalizeNavigationSpanFromRouterState(span, router.state);\n } else {\n updateNavigationSpanUrlFromLocation(span);\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,9 +1,7 @@
1
1
  export * from '@sentry/node';
2
2
  export { init } from './server/sdk.js';
3
- export { sentryHandleRequest, wrapSentryHandleRequest } from './server/wrapSentryHandleRequest.js';
3
+ export { wrapSentryHandleRequest } from './server/wrapSentryHandleRequest.js';
4
4
  export { createSentryHandleRequest } from './server/createSentryHandleRequest.js';
5
- export { wrapServerAction } from './server/wrapServerAction.js';
6
- export { wrapServerLoader } from './server/wrapServerLoader.js';
7
5
  export { createSentryHandleError } from './server/createSentryHandleError.js';
8
6
  export { getMetaTagTransformer } from './server/getMetaTagTransformer.js';
9
7
  export { createSentryServerInstrumentation } from './server/createServerInstrumentation.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
@@ -1 +1 @@
1
- {"type":"module","version":"10.70.0"}
1
+ {"type":"module","version":"11.0.0-alpha.1"}
@@ -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":["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;;;;"}
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 & 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,aAAa,CAAA;AAC9C;;;;"}
@@ -1,13 +1,13 @@
1
- import { createContextKey, context } from '@opentelemetry/api';
2
- import { HTTP_ROUTE, URL_PATH, URL_FULL, HTTP_REQUEST_METHOD } from '@sentry/conventions/attributes';
3
- import { debug, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, SPAN_STATUS_ERROR, getActiveSpan, getRootSpan, updateSpanName, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, flushIfServerless, getCurrentScope } from '@sentry/core';
1
+ import { CODE_FUNCTION_NAME, SENTRY_OP, HTTP_ROUTE, URL_PATH, URL_FULL, HTTP_REQUEST_METHOD } from '@sentry/conventions/attributes';
2
+ import { WEB_SERVER_FUNCTION_SPAN_OP, WEB_SERVER_MIDDLEWARE_SPAN_OP } from '@sentry/conventions/op';
3
+ import { debug, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_STATUS_ERROR, getActiveSpan, getRootSpan, updateSpanName, filterCollectedUrl, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_OP, flushIfServerless, getCurrentScope } from '@sentry/core';
4
4
  import { DEBUG_BUILD } from '../common/debug-build.js';
5
5
  import { captureInstrumentationError, getPathFromRequest, getPattern, normalizeRoutePath } from '../common/utils.js';
6
6
  import { getMiddlewareName } from './serverBuild.js';
7
7
  import { markInstrumentationApiUsed } from './serverGlobals.js';
8
8
  export { isInstrumentationApiUsed } from './serverGlobals.js';
9
9
 
10
- const MIDDLEWARE_COUNTER_KEY = createContextKey("sentry_react_router_middleware_counter");
10
+ const middlewareCountersByRootSpan = /* @__PURE__ */ new WeakMap();
11
11
  function createSentryServerInstrumentation(options = {}) {
12
12
  const { captureErrors = true } = options;
13
13
  DEBUG_BUILD && debug.log("React Router server instrumentation created.");
@@ -19,61 +19,57 @@ function createSentryServerInstrumentation(options = {}) {
19
19
  const pathname = getPathFromRequest(info.request);
20
20
  const activeSpan = getActiveSpan();
21
21
  const existingRootSpan = activeSpan ? getRootSpan(activeSpan) : void 0;
22
- const counterStore = { counters: {} };
23
- const ctx = context.active().setValue(MIDDLEWARE_COUNTER_KEY, counterStore);
24
- await context.with(ctx, async () => {
25
- if (existingRootSpan) {
26
- updateSpanName(existingRootSpan, `${info.request.method} ${pathname}`);
27
- existingRootSpan.setAttributes({
28
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
29
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.instrumentation_api",
30
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
31
- [URL_FULL]: info.request.url,
32
- [URL_PATH]: pathname
33
- });
34
- try {
35
- const result = await handleRequest();
36
- if (result.status === "error" && result.error instanceof Error) {
37
- existingRootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
38
- captureInstrumentationError(result, captureErrors, "react_router.request_handler", {
39
- "http.method": info.request.method,
40
- "http.url": pathname
41
- });
42
- }
43
- } finally {
44
- await flushIfServerless();
22
+ if (existingRootSpan) {
23
+ updateSpanName(existingRootSpan, `${info.request.method} ${pathname}`);
24
+ existingRootSpan.setAttributes({
25
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
26
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.instrumentation_api",
27
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
28
+ [URL_FULL]: filterCollectedUrl(info.request.url),
29
+ [URL_PATH]: pathname
30
+ });
31
+ try {
32
+ const result = await handleRequest();
33
+ if (result.status === "error" && result.error instanceof Error) {
34
+ existingRootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
35
+ captureInstrumentationError(result, captureErrors, "react_router.request_handler", {
36
+ "http.method": info.request.method,
37
+ [URL_FULL]: pathname
38
+ });
45
39
  }
46
- } else {
47
- await startSpan(
48
- {
49
- name: `${info.request.method} ${pathname}`,
50
- forceTransaction: true,
51
- attributes: {
52
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
53
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.instrumentation_api",
54
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
55
- [HTTP_REQUEST_METHOD]: info.request.method,
56
- [URL_PATH]: pathname,
57
- [URL_FULL]: info.request.url
58
- }
59
- },
60
- async (span) => {
61
- try {
62
- const result = await handleRequest();
63
- if (result.status === "error" && result.error instanceof Error) {
64
- span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
65
- captureInstrumentationError(result, captureErrors, "react_router.request_handler", {
66
- "http.method": info.request.method,
67
- "http.url": pathname
68
- });
69
- }
70
- } finally {
71
- await flushIfServerless();
40
+ } finally {
41
+ await flushIfServerless();
42
+ }
43
+ } else {
44
+ await startSpan(
45
+ {
46
+ name: `${info.request.method} ${pathname}`,
47
+ forceTransaction: true,
48
+ attributes: {
49
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
50
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.instrumentation_api",
51
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
52
+ [HTTP_REQUEST_METHOD]: info.request.method,
53
+ [URL_PATH]: pathname,
54
+ [URL_FULL]: filterCollectedUrl(info.request.url)
55
+ }
56
+ },
57
+ async (span) => {
58
+ try {
59
+ const result = await handleRequest();
60
+ if (result.status === "error" && result.error instanceof Error) {
61
+ span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
62
+ captureInstrumentationError(result, captureErrors, "react_router.request_handler", {
63
+ "http.method": info.request.method,
64
+ [URL_FULL]: pathname
65
+ });
72
66
  }
67
+ } finally {
68
+ await flushIfServerless();
73
69
  }
74
- );
75
- }
76
- });
70
+ }
71
+ );
72
+ }
77
73
  }
78
74
  });
79
75
  },
@@ -90,7 +86,8 @@ function createSentryServerInstrumentation(options = {}) {
90
86
  {
91
87
  name: routePattern,
92
88
  attributes: {
93
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.loader",
89
+ [SENTRY_OP]: WEB_SERVER_FUNCTION_SPAN_OP,
90
+ [CODE_FUNCTION_NAME]: "loader",
94
91
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
95
92
  }
96
93
  },
@@ -100,7 +97,7 @@ function createSentryServerInstrumentation(options = {}) {
100
97
  span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
101
98
  captureInstrumentationError(result, captureErrors, "react_router.loader", {
102
99
  "http.method": info.request.method,
103
- "http.url": urlPath
100
+ [URL_FULL]: urlPath
104
101
  });
105
102
  }
106
103
  }
@@ -115,7 +112,8 @@ function createSentryServerInstrumentation(options = {}) {
115
112
  {
116
113
  name: routePattern,
117
114
  attributes: {
118
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.action",
115
+ [SENTRY_OP]: WEB_SERVER_FUNCTION_SPAN_OP,
116
+ [CODE_FUNCTION_NAME]: "action",
119
117
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
120
118
  }
121
119
  },
@@ -125,7 +123,7 @@ function createSentryServerInstrumentation(options = {}) {
125
123
  span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
126
124
  captureInstrumentationError(result, captureErrors, "react_router.action", {
127
125
  "http.method": info.request.method,
128
- "http.url": urlPath
126
+ [URL_FULL]: urlPath
129
127
  });
130
128
  }
131
129
  }
@@ -136,18 +134,25 @@ function createSentryServerInstrumentation(options = {}) {
136
134
  const pattern = getPattern(info);
137
135
  const routePattern = normalizeRoutePath(pattern) || urlPath;
138
136
  updateRootSpanWithRoute(info.request.method, pattern, urlPath);
139
- const counterStore = context.active().getValue(MIDDLEWARE_COUNTER_KEY);
137
+ const activeSpan = getActiveSpan();
138
+ const rootSpan = activeSpan ? getRootSpan(activeSpan) : void 0;
140
139
  let middlewareIndex = 0;
141
- if (counterStore) {
142
- middlewareIndex = counterStore.counters[routeId] ?? 0;
143
- counterStore.counters[routeId] = middlewareIndex + 1;
140
+ if (rootSpan) {
141
+ let counters = middlewareCountersByRootSpan.get(rootSpan);
142
+ if (!counters) {
143
+ counters = {};
144
+ middlewareCountersByRootSpan.set(rootSpan, counters);
145
+ }
146
+ middlewareIndex = counters[routeId] ?? 0;
147
+ counters[routeId] = middlewareIndex + 1;
144
148
  }
145
149
  const middlewareName = getMiddlewareName(routeId, middlewareIndex);
146
150
  await startSpan(
147
151
  {
148
152
  name: `middleware ${middlewareName || routeId}`,
149
153
  attributes: {
150
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.middleware",
154
+ [SENTRY_OP]: WEB_SERVER_MIDDLEWARE_SPAN_OP,
155
+ [CODE_FUNCTION_NAME]: "middleware",
151
156
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api",
152
157
  "react_router.route.id": routeId,
153
158
  [HTTP_ROUTE]: routePattern,
@@ -161,7 +166,7 @@ function createSentryServerInstrumentation(options = {}) {
161
166
  span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
162
167
  captureInstrumentationError(result, captureErrors, "react_router.middleware", {
163
168
  "http.method": info.request.method,
164
- "http.url": urlPath
169
+ [URL_FULL]: urlPath
165
170
  });
166
171
  }
167
172
  }
@@ -172,7 +177,8 @@ function createSentryServerInstrumentation(options = {}) {
172
177
  {
173
178
  name: "Lazy Route Load",
174
179
  attributes: {
175
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "function.react_router.lazy",
180
+ [SENTRY_OP]: WEB_SERVER_FUNCTION_SPAN_OP,
181
+ [CODE_FUNCTION_NAME]: "lazy",
176
182
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
177
183
  }
178
184
  },
@@ -1 +1 @@
1
- {"version":3,"file":"createServerInstrumentation.js","sources":["../../../src/server/createServerInstrumentation.ts"],"sourcesContent":["import { context, createContextKey } from '@opentelemetry/api';\nimport { HTTP_REQUEST_METHOD, HTTP_ROUTE, URL_FULL, URL_PATH } from '@sentry/conventions/attributes';\nimport {\n debug,\n flushIfServerless,\n getActiveSpan,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n SPAN_STATUS_ERROR,\n startSpan,\n updateSpanName,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport type { InstrumentableRequestHandler, InstrumentableRoute, ServerInstrumentation } from '../common/types';\nimport { captureInstrumentationError, getPathFromRequest, getPattern, normalizeRoutePath } from '../common/utils';\nimport { getMiddlewareName } from './serverBuild';\nimport { markInstrumentationApiUsed } from './serverGlobals';\n\nconst MIDDLEWARE_COUNTER_KEY = createContextKey('sentry_react_router_middleware_counter');\n\n// Re-export for backward compatibility and external use\nexport { isInstrumentationApiUsed } from './serverGlobals';\n\n/**\n * Options for creating Sentry server instrumentation.\n */\nexport interface CreateSentryServerInstrumentationOptions {\n /**\n * Whether to capture errors from loaders/actions automatically.\n * @default true\n */\n captureErrors?: boolean;\n}\n\n/**\n * Creates a Sentry server instrumentation for React Router's instrumentation API.\n */\nexport function createSentryServerInstrumentation(\n options: CreateSentryServerInstrumentationOptions = {},\n): ServerInstrumentation {\n const { captureErrors = true } = options;\n\n DEBUG_BUILD && debug.log('React Router server instrumentation created.');\n\n return {\n handler(handler: InstrumentableRequestHandler) {\n // Mark the instrumentation API active only when React Router actually invokes this\n markInstrumentationApiUsed();\n handler.instrument({\n async request(handleRequest, info) {\n const pathname = getPathFromRequest(info.request);\n const activeSpan = getActiveSpan();\n const existingRootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n const counterStore = { counters: {} as Record<string, number> };\n const ctx = context.active().setValue(MIDDLEWARE_COUNTER_KEY, counterStore);\n\n await context.with(ctx, async () => {\n if (existingRootSpan) {\n updateSpanName(existingRootSpan, `${info.request.method} ${pathname}`);\n existingRootSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [URL_FULL]: info.request.url,\n [URL_PATH]: pathname,\n });\n\n try {\n const result = await handleRequest();\n if (result.status === 'error' && result.error instanceof Error) {\n existingRootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {\n 'http.method': info.request.method,\n 'http.url': pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n } else {\n await startSpan(\n {\n name: `${info.request.method} ${pathname}`,\n forceTransaction: true,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_PATH]: pathname,\n [URL_FULL]: info.request.url,\n },\n },\n async span => {\n try {\n const result = await handleRequest();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {\n 'http.method': info.request.method,\n 'http.url': pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n },\n );\n }\n });\n },\n });\n },\n\n route(route: InstrumentableRoute) {\n // Also mark active here, in case route registration runs (mirrors the handler callback above).\n markInstrumentationApiUsed();\n const routeId = route.id;\n\n route.instrument({\n async loader(callLoader, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.loader',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLoader();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.loader', {\n 'http.method': info.request.method,\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async action(callAction, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.action',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callAction();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.action', {\n 'http.method': info.request.method,\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async middleware(callMiddleware, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n const counterStore = context.active().getValue(MIDDLEWARE_COUNTER_KEY) as\n | { counters: Record<string, number> }\n | undefined;\n let middlewareIndex = 0;\n if (counterStore) {\n middlewareIndex = counterStore.counters[routeId] ?? 0;\n counterStore.counters[routeId] = middlewareIndex + 1;\n }\n\n const middlewareName = getMiddlewareName(routeId, middlewareIndex);\n\n await startSpan(\n {\n name: `middleware ${middlewareName || routeId}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.middleware',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n 'react_router.route.id': routeId,\n [HTTP_ROUTE]: routePattern,\n ...(middlewareName && { 'react_router.middleware.name': middlewareName }),\n 'react_router.middleware.index': middlewareIndex,\n },\n },\n async span => {\n const result = await callMiddleware();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.middleware', {\n 'http.method': info.request.method,\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async lazy(callLazy) {\n await startSpan(\n {\n name: 'Lazy Route Load',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.lazy',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLazy();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.lazy', {});\n }\n },\n );\n },\n });\n },\n };\n}\n\nfunction updateRootSpanWithRoute(method: string, pattern: string | undefined, urlPath: string): void {\n const activeSpan = getActiveSpan();\n if (!activeSpan) return;\n const rootSpan = getRootSpan(activeSpan);\n if (!rootSpan) return;\n\n // Skip update if URL path is invalid (failed to parse)\n if (!urlPath || urlPath === '<unknown>') {\n DEBUG_BUILD && debug.warn('Cannot update span with invalid URL path:', urlPath);\n return;\n }\n\n const hasPattern = !!pattern;\n const routeName = hasPattern ? normalizeRoutePath(pattern) || urlPath : urlPath;\n\n const transactionName = `${method} ${routeName}`;\n updateSpanName(rootSpan, transactionName);\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: hasPattern ? 'route' : 'url',\n });\n\n // Also update the scope's transaction name so errors captured during this request\n // have the correct transaction name (not the initial placeholder like \"GET *\")\n getCurrentScope().setTransactionName(transactionName);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createServerInstrumentation.js","sources":["../../../src/server/createServerInstrumentation.ts"],"sourcesContent":["import {\n CODE_FUNCTION_NAME,\n HTTP_REQUEST_METHOD,\n HTTP_ROUTE,\n SENTRY_OP,\n URL_FULL,\n URL_PATH,\n} from '@sentry/conventions/attributes';\nimport { WEB_SERVER_FUNCTION_SPAN_OP, WEB_SERVER_MIDDLEWARE_SPAN_OP } from '@sentry/conventions/op';\nimport {\n debug,\n flushIfServerless,\n getActiveSpan,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n SPAN_STATUS_ERROR,\n startSpan,\n updateSpanName,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport type { InstrumentableRequestHandler, InstrumentableRoute, ServerInstrumentation } from '../common/types';\nimport { captureInstrumentationError, getPathFromRequest, getPattern, normalizeRoutePath } from '../common/utils';\nimport { getMiddlewareName } from './serverBuild';\nimport { markInstrumentationApiUsed } from './serverGlobals';\n\n// Per-request middleware counters, keyed by the request's root span (the one transaction all of a\n// request's middlewares run under). The root span is the same instance across those middleware hooks\n// whether or not a Sentry OpenTelemetry tracer provider is set up, unlike the OTel context the counter\n// used to live on (which does not propagate without a provider).\nconst middlewareCountersByRootSpan = new WeakMap<object, Record<string, number>>();\n\n// Re-export for backward compatibility and external use\nexport { isInstrumentationApiUsed } from './serverGlobals';\n\n/**\n * Options for creating Sentry server instrumentation.\n */\nexport interface CreateSentryServerInstrumentationOptions {\n /**\n * Whether to capture errors from loaders/actions automatically.\n * @default true\n */\n captureErrors?: boolean;\n}\n\n/**\n * Creates a Sentry server instrumentation for React Router's instrumentation API.\n */\nexport function createSentryServerInstrumentation(\n options: CreateSentryServerInstrumentationOptions = {},\n): ServerInstrumentation {\n const { captureErrors = true } = options;\n\n DEBUG_BUILD && debug.log('React Router server instrumentation created.');\n\n return {\n handler(handler: InstrumentableRequestHandler) {\n // Mark the instrumentation API active only when React Router actually invokes this\n markInstrumentationApiUsed();\n handler.instrument({\n async request(handleRequest, info) {\n const pathname = getPathFromRequest(info.request);\n const activeSpan = getActiveSpan();\n const existingRootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n if (existingRootSpan) {\n updateSpanName(existingRootSpan, `${info.request.method} ${pathname}`);\n existingRootSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [URL_FULL]: filterCollectedUrl(info.request.url),\n [URL_PATH]: pathname,\n });\n\n try {\n const result = await handleRequest();\n if (result.status === 'error' && result.error instanceof Error) {\n existingRootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {\n 'http.method': info.request.method,\n [URL_FULL]: pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n } else {\n await startSpan(\n {\n name: `${info.request.method} ${pathname}`,\n forceTransaction: true,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_PATH]: pathname,\n [URL_FULL]: filterCollectedUrl(info.request.url),\n },\n },\n async span => {\n try {\n const result = await handleRequest();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {\n 'http.method': info.request.method,\n [URL_FULL]: pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n },\n );\n }\n },\n });\n },\n\n route(route: InstrumentableRoute) {\n // Also mark active here, in case route registration runs (mirrors the handler callback above).\n markInstrumentationApiUsed();\n const routeId = route.id;\n\n route.instrument({\n async loader(callLoader, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: WEB_SERVER_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'loader',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLoader();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.loader', {\n 'http.method': info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async action(callAction, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: WEB_SERVER_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'action',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callAction();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.action', {\n 'http.method': info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async middleware(callMiddleware, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n let middlewareIndex = 0;\n if (rootSpan) {\n let counters = middlewareCountersByRootSpan.get(rootSpan);\n if (!counters) {\n counters = {};\n middlewareCountersByRootSpan.set(rootSpan, counters);\n }\n middlewareIndex = counters[routeId] ?? 0;\n counters[routeId] = middlewareIndex + 1;\n }\n\n const middlewareName = getMiddlewareName(routeId, middlewareIndex);\n\n await startSpan(\n {\n name: `middleware ${middlewareName || routeId}`,\n attributes: {\n [SENTRY_OP]: WEB_SERVER_MIDDLEWARE_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'middleware',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n 'react_router.route.id': routeId,\n [HTTP_ROUTE]: routePattern,\n ...(middlewareName && { 'react_router.middleware.name': middlewareName }),\n 'react_router.middleware.index': middlewareIndex,\n },\n },\n async span => {\n const result = await callMiddleware();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.middleware', {\n 'http.method': info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async lazy(callLazy) {\n await startSpan(\n {\n name: 'Lazy Route Load',\n attributes: {\n [SENTRY_OP]: WEB_SERVER_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'lazy',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLazy();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.lazy', {});\n }\n },\n );\n },\n });\n },\n };\n}\n\nfunction updateRootSpanWithRoute(method: string, pattern: string | undefined, urlPath: string): void {\n const activeSpan = getActiveSpan();\n if (!activeSpan) return;\n const rootSpan = getRootSpan(activeSpan);\n if (!rootSpan) return;\n\n // Skip update if URL path is invalid (failed to parse)\n if (!urlPath || urlPath === '<unknown>') {\n DEBUG_BUILD && debug.warn('Cannot update span with invalid URL path:', urlPath);\n return;\n }\n\n const hasPattern = !!pattern;\n const routeName = hasPattern ? normalizeRoutePath(pattern) || urlPath : urlPath;\n\n const transactionName = `${method} ${routeName}`;\n updateSpanName(rootSpan, transactionName);\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: hasPattern ? 'route' : 'url',\n });\n\n // Also update the scope's transaction name so errors captured during this request\n // have the correct transaction name (not the initial placeholder like \"GET *\")\n getCurrentScope().setTransactionName(transactionName);\n}\n"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ const LOW_QUALITY_TRANSACTIONS_FILTERS = [
8
8
  // Filter by `http.target` instead, which carries the raw request path.
9
9
  { attributes: { "http.target": /\/__manifest/ } }
10
10
  ];
11
- const _lowQualityTransactionsFilterIntegration = ((_options) => ({
11
+ const _lowQualityTransactionsFilterIntegration = (() => ({
12
12
  name: "LowQualityTransactionsFilter",
13
13
  beforeSetup(client) {
14
14
  const opts = client.getOptions();
@@ -1 +1 @@
1
- {"version":3,"file":"lowQualityTransactionsFilterIntegration.js","sources":["../../../../src/server/integration/lowQualityTransactionsFilterIntegration.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\nimport type { NodeOptions } from '@sentry/node';\n\nconst LOW_QUALITY_TRANSACTIONS_FILTERS = [\n /GET \\/node_modules\\//,\n /GET \\/favicon\\.ico/,\n /GET \\/@id\\//,\n // The span description for the `__manifest` endpoint is `GET *` (`http.route` resolves to `*`).\n // Filter by `http.target` instead, which carries the raw request path.\n { attributes: { 'http.target': /\\/__manifest/ } },\n];\n\n// TODO(v11): Remove the `_options` parameter (unused and only kept for back-compat with the previous signature)\nconst _lowQualityTransactionsFilterIntegration = ((_options?: NodeOptions) => ({\n name: 'LowQualityTransactionsFilter' as const,\n beforeSetup(client) {\n const opts = client.getOptions();\n opts.ignoreSpans = [...(opts.ignoreSpans || []), ...LOW_QUALITY_TRANSACTIONS_FILTERS];\n },\n})) satisfies IntegrationFn;\n\n/**\n * Integration that filters out noisy http transactions such as requests to node_modules, favicon.ico, @id/, __manifest.\n * Adds entries to `ignoreSpans` so the filter applies in both static and streaming trace lifecycles.\n */\nexport const lowQualityTransactionsFilterIntegration = defineIntegration(_lowQualityTransactionsFilterIntegration);\n"],"names":[],"mappings":";;AAIA,MAAM,gCAAA,GAAmC;AAAA,EACvC,sBAAA;AAAA,EACA,oBAAA;AAAA,EACA,aAAA;AAAA;AAAA;AAAA,EAGA,EAAE,UAAA,EAAY,EAAE,aAAA,EAAe,gBAAe;AAChD,CAAA;AAGA,MAAM,wCAAA,IAA4C,CAAC,QAAA,MAA4B;AAAA,EAC7E,IAAA,EAAM,8BAAA;AAAA,EACN,YAAY,MAAA,EAAQ;AAClB,IAAA,MAAM,IAAA,GAAO,OAAO,UAAA,EAAW;AAC/B,IAAA,IAAA,CAAK,WAAA,GAAc,CAAC,GAAI,IAAA,CAAK,eAAe,EAAC,EAAI,GAAG,gCAAgC,CAAA;AAAA,EACtF;AACF,CAAA,CAAA,CAAA;AAMO,MAAM,uCAAA,GAA0C,kBAAkB,wCAAwC;;;;"}
1
+ {"version":3,"file":"lowQualityTransactionsFilterIntegration.js","sources":["../../../../src/server/integration/lowQualityTransactionsFilterIntegration.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\n\nconst LOW_QUALITY_TRANSACTIONS_FILTERS = [\n /GET \\/node_modules\\//,\n /GET \\/favicon\\.ico/,\n /GET \\/@id\\//,\n // The span description for the `__manifest` endpoint is `GET *` (`http.route` resolves to `*`).\n // Filter by `http.target` instead, which carries the raw request path.\n { attributes: { 'http.target': /\\/__manifest/ } },\n];\n\nconst _lowQualityTransactionsFilterIntegration = (() => ({\n name: 'LowQualityTransactionsFilter' as const,\n beforeSetup(client) {\n const opts = client.getOptions();\n opts.ignoreSpans = [...(opts.ignoreSpans || []), ...LOW_QUALITY_TRANSACTIONS_FILTERS];\n },\n})) satisfies IntegrationFn;\n\n/**\n * Integration that filters out noisy http transactions such as requests to node_modules, favicon.ico, @id/, __manifest.\n * Adds entries to `ignoreSpans` so the filter applies in both static and streaming trace lifecycles.\n */\nexport const lowQualityTransactionsFilterIntegration = defineIntegration(_lowQualityTransactionsFilterIntegration);\n"],"names":[],"mappings":";;AAGA,MAAM,gCAAA,GAAmC;AAAA,EACvC,sBAAA;AAAA,EACA,oBAAA;AAAA,EACA,aAAA;AAAA;AAAA;AAAA,EAGA,EAAE,UAAA,EAAY,EAAE,aAAA,EAAe,gBAAe;AAChD,CAAA;AAEA,MAAM,4CAA4C,OAAO;AAAA,EACvD,IAAA,EAAM,8BAAA;AAAA,EACN,YAAY,MAAA,EAAQ;AAClB,IAAA,MAAM,IAAA,GAAO,OAAO,UAAA,EAAW;AAC/B,IAAA,IAAA,CAAK,WAAA,GAAc,CAAC,GAAI,IAAA,CAAK,eAAe,EAAC,EAAI,GAAG,gCAAgC,CAAA;AAAA,EACtF;AACF,CAAA,CAAA,CAAA;AAMO,MAAM,uCAAA,GAA0C,kBAAkB,wCAAwC;;;;"}
@@ -1,53 +1,15 @@
1
- import { HTTP_ROUTE } from '@sentry/conventions/attributes';
2
- import { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
3
- import { generateInstrumentOnce, NODE_VERSION } from '@sentry/node';
4
- import { ReactRouterInstrumentation } from '../instrumentation/reactRouter.js';
1
+ import { defineIntegration } from '@sentry/core';
5
2
  import { registerServerBuildGlobal } from '../serverBuild.js';
6
- import { enableOtelDataLoaderSpanCreation } from '../serverGlobals.js';
7
3
 
8
4
  const INTEGRATION_NAME = "ReactRouterServer";
9
- const instrumentReactRouter = generateInstrumentOnce(INTEGRATION_NAME, () => {
10
- return new ReactRouterInstrumentation();
11
- });
12
- const instrumentReactRouterServer = Object.assign(
13
- () => {
14
- instrumentReactRouter();
15
- registerServerBuildGlobal();
16
- },
17
- { id: INTEGRATION_NAME }
18
- );
19
5
  const reactRouterServerIntegration = defineIntegration(() => {
20
6
  return {
21
7
  name: INTEGRATION_NAME,
22
8
  setupOnce() {
23
- if (NODE_VERSION.major === 20 && NODE_VERSION.minor < 19 || NODE_VERSION.major === 22 && NODE_VERSION.minor < 12) {
24
- enableOtelDataLoaderSpanCreation();
25
- }
26
- instrumentReactRouterServer();
27
- },
28
- processEvent(event) {
29
- if (event.type === "transaction" && event.contexts?.trace?.data && event.contexts.trace.data[HTTP_ROUTE] === "*") {
30
- const origin = event.contexts.trace.origin;
31
- const isInstrumentationApiOrigin = origin?.includes("instrumentation_api");
32
- if (isInstrumentationApiOrigin || !event.transaction?.endsWith(" *")) {
33
- delete event.contexts.trace.data[HTTP_ROUTE];
34
- }
35
- }
36
- return event;
37
- },
38
- processSegmentSpan(span) {
39
- const attributes = span.attributes;
40
- if (attributes?.[HTTP_ROUTE] !== "*") {
41
- return;
42
- }
43
- const origin = attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN];
44
- const isInstrumentationApiOrigin = typeof origin === "string" && origin.includes("instrumentation_api");
45
- if (isInstrumentationApiOrigin || !span.name?.endsWith(" *")) {
46
- delete attributes[HTTP_ROUTE];
47
- }
9
+ registerServerBuildGlobal();
48
10
  }
49
11
  };
50
12
  });
51
13
 
52
- export { instrumentReactRouterServer, reactRouterServerIntegration };
14
+ export { reactRouterServerIntegration };
53
15
  //# sourceMappingURL=reactRouterServer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reactRouterServer.js","sources":["../../../../src/server/integration/reactRouterServer.ts"],"sourcesContent":["import { HTTP_ROUTE } from '@sentry/conventions/attributes';\nimport { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';\nimport { generateInstrumentOnce, NODE_VERSION } from '@sentry/node';\nimport { ReactRouterInstrumentation } from '../instrumentation/reactRouter';\nimport { registerServerBuildGlobal } from '../serverBuild';\nimport { enableOtelDataLoaderSpanCreation } from '../serverGlobals';\n\nconst INTEGRATION_NAME = 'ReactRouterServer' as const;\n\nconst instrumentReactRouter = generateInstrumentOnce(INTEGRATION_NAME, () => {\n return new ReactRouterInstrumentation();\n});\n\nexport const instrumentReactRouterServer = Object.assign(\n (): void => {\n instrumentReactRouter();\n // Register global for Vite plugin ServerBuild capture\n registerServerBuildGlobal();\n },\n { id: INTEGRATION_NAME },\n);\n\n/**\n * Integration capturing tracing data for React Router server functions.\n */\nexport const reactRouterServerIntegration = defineIntegration(() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // Enable OTEL data-loader spans only on Node versions without the diagnostics_channel-based instrumentation API.\n if (\n (NODE_VERSION.major === 20 && NODE_VERSION.minor < 19) ||\n (NODE_VERSION.major === 22 && NODE_VERSION.minor < 12)\n ) {\n enableOtelDataLoaderSpanCreation();\n }\n\n // Always install to capture ServerBuild for middleware names.\n // Skips per-request wrapping when instrumentation API is active or OTEL span creation is disabled.\n instrumentReactRouterServer();\n },\n processEvent(event) {\n // Express generates bogus `*` routes for data loaders, which we want to remove here\n // we cannot do this earlier because some OTEL instrumentation adds this at some unexpected point\n if (\n event.type === 'transaction' &&\n event.contexts?.trace?.data &&\n event.contexts.trace.data[HTTP_ROUTE] === '*'\n ) {\n const origin = event.contexts.trace.origin;\n const isInstrumentationApiOrigin = origin?.includes('instrumentation_api');\n\n // For instrumentation_api, always clean up bogus `*` route since we set better names\n // For legacy, only clean up if the name has been adjusted (not METHOD *)\n if (isInstrumentationApiOrigin || !event.transaction?.endsWith(' *')) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete event.contexts.trace.data[HTTP_ROUTE];\n }\n }\n\n return event;\n },\n processSegmentSpan(span) {\n // Express generates bogus `*` routes for data loaders, which we want to remove here\n // we cannot do this earlier because some OTEL instrumentation adds this at some unexpected point\n const attributes = span.attributes;\n if (attributes?.[HTTP_ROUTE] !== '*') {\n return;\n }\n\n const origin = attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN];\n const isInstrumentationApiOrigin = typeof origin === 'string' && origin.includes('instrumentation_api');\n\n // For instrumentation_api, always clean up bogus `*` route since we set better names\n // For legacy, only clean up if the name has been adjusted (not METHOD *)\n if (isInstrumentationApiOrigin || !span.name?.endsWith(' *')) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete attributes[HTTP_ROUTE];\n }\n },\n };\n});\n"],"names":[],"mappings":";;;;;;;AAOA,MAAM,gBAAA,GAAmB,mBAAA;AAEzB,MAAM,qBAAA,GAAwB,sBAAA,CAAuB,gBAAA,EAAkB,MAAM;AAC3E,EAAA,OAAO,IAAI,0BAAA,EAA2B;AACxC,CAAC,CAAA;AAEM,MAAM,8BAA8B,MAAA,CAAO,MAAA;AAAA,EAChD,MAAY;AACV,IAAA,qBAAA,EAAsB;AAEtB,IAAA,yBAAA,EAA0B;AAAA,EAC5B,CAAA;AAAA,EACA,EAAE,IAAI,gBAAA;AACR;AAKO,MAAM,4BAAA,GAA+B,kBAAkB,MAAM;AAClE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,GAAY;AAEV,MAAA,IACG,YAAA,CAAa,KAAA,KAAU,EAAA,IAAM,YAAA,CAAa,KAAA,GAAQ,EAAA,IAClD,YAAA,CAAa,KAAA,KAAU,EAAA,IAAM,YAAA,CAAa,KAAA,GAAQ,EAAA,EACnD;AACA,QAAA,gCAAA,EAAiC;AAAA,MACnC;AAIA,MAAA,2BAAA,EAA4B;AAAA,IAC9B,CAAA;AAAA,IACA,aAAa,KAAA,EAAO;AAGlB,MAAA,IACE,KAAA,CAAM,IAAA,KAAS,aAAA,IACf,KAAA,CAAM,QAAA,EAAU,KAAA,EAAO,IAAA,IACvB,KAAA,CAAM,QAAA,CAAS,KAAA,CAAM,IAAA,CAAK,UAAU,MAAM,GAAA,EAC1C;AACA,QAAA,MAAM,MAAA,GAAS,KAAA,CAAM,QAAA,CAAS,KAAA,CAAM,MAAA;AACpC,QAAA,MAAM,0BAAA,GAA6B,MAAA,EAAQ,QAAA,CAAS,qBAAqB,CAAA;AAIzE,QAAA,IAAI,8BAA8B,CAAC,KAAA,CAAM,WAAA,EAAa,QAAA,CAAS,IAAI,CAAA,EAAG;AAEpE,UAAA,OAAO,KAAA,CAAM,QAAA,CAAS,KAAA,CAAM,IAAA,CAAK,UAAU,CAAA;AAAA,QAC7C;AAAA,MACF;AAEA,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,mBAAmB,IAAA,EAAM;AAGvB,MAAA,MAAM,aAAa,IAAA,CAAK,UAAA;AACxB,MAAA,IAAI,UAAA,GAAa,UAAU,CAAA,KAAM,GAAA,EAAK;AACpC,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,MAAA,GAAS,WAAW,gCAAgC,CAAA;AAC1D,MAAA,MAAM,6BAA6B,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,CAAO,SAAS,qBAAqB,CAAA;AAItG,MAAA,IAAI,8BAA8B,CAAC,IAAA,CAAK,IAAA,EAAM,QAAA,CAAS,IAAI,CAAA,EAAG;AAE5D,QAAA,OAAO,WAAW,UAAU,CAAA;AAAA,MAC9B;AAAA,IACF;AAAA,GACF;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"reactRouterServer.js","sources":["../../../../src/server/integration/reactRouterServer.ts"],"sourcesContent":["import { defineIntegration } from '@sentry/core';\nimport { registerServerBuildGlobal } from '../serverBuild';\n\nconst INTEGRATION_NAME = 'ReactRouterServer' as const;\n\n/**\n * Integration capturing tracing data for React Router server functions.\n */\nexport const reactRouterServerIntegration = defineIntegration(() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // Register global for Vite plugin ServerBuild capture (used for middleware name resolution).\n registerServerBuildGlobal();\n },\n };\n});\n"],"names":[],"mappings":";;;AAGA,MAAM,gBAAA,GAAmB,mBAAA;AAKlB,MAAM,4BAAA,GAA+B,kBAAkB,MAAM;AAClE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,GAAY;AAEV,MAAA,yBAAA,EAA0B;AAAA,IAC5B;AAAA,GACF;AACF,CAAC;;;;"}
@@ -7,7 +7,7 @@ import { reactRouterServerIntegration } from './integration/reactRouterServer.js
7
7
  function getDefaultReactRouterServerIntegrations(options) {
8
8
  return [
9
9
  ...getDefaultIntegrations(options),
10
- lowQualityTransactionsFilterIntegration(options),
10
+ lowQualityTransactionsFilterIntegration(),
11
11
  reactRouterServerIntegration()
12
12
  ];
13
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { applySdkMetadata, debug, setTag } from '@sentry/core';\nimport type { NodeClient, NodeOptions } from '@sentry/node';\nimport { getDefaultIntegrations as getNodeDefaultIntegrations, init as initNodeSdk } from '@sentry/node';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport { lowQualityTransactionsFilterIntegration } from './integration/lowQualityTransactionsFilterIntegration';\nimport { reactRouterServerIntegration } from './integration/reactRouterServer';\n\n/**\n * Returns the default integrations for the React Router SDK.\n * @param options The options for the SDK.\n */\nexport function getDefaultReactRouterServerIntegrations(options: NodeOptions): Integration[] {\n return [\n ...getNodeDefaultIntegrations(options),\n lowQualityTransactionsFilterIntegration(options),\n reactRouterServerIntegration(),\n ];\n}\n\n/**\n * Initializes the server side of the React Router SDK\n */\nexport function init(options: NodeOptions): NodeClient | undefined {\n const opts: NodeOptions = {\n ...options,\n defaultIntegrations: getDefaultReactRouterServerIntegrations(options),\n };\n\n DEBUG_BUILD && debug.log('Initializing SDK...');\n\n applySdkMetadata(opts, 'react-router', ['react-router', 'node']);\n\n const client = initNodeSdk(opts);\n\n setTag('runtime', 'node');\n\n DEBUG_BUILD && debug.log('SDK successfully initialized');\n\n return client;\n}\n"],"names":["getNodeDefaultIntegrations","initNodeSdk"],"mappings":";;;;;;AAYO,SAAS,wCAAwC,OAAA,EAAqC;AAC3F,EAAA,OAAO;AAAA,IACL,GAAGA,uBAA2B,OAAO,CAAA;AAAA,IACrC,wCAAwC,OAAO,CAAA;AAAA,IAC/C,4BAAA;AAA6B,GAC/B;AACF;AAKO,SAAS,KAAK,OAAA,EAA8C;AACjE,EAAA,MAAM,IAAA,GAAoB;AAAA,IACxB,GAAG,OAAA;AAAA,IACH,mBAAA,EAAqB,wCAAwC,OAAO;AAAA,GACtE;AAEA,EAAA,WAAA,IAAe,KAAA,CAAM,IAAI,qBAAqB,CAAA;AAE9C,EAAA,gBAAA,CAAiB,IAAA,EAAM,cAAA,EAAgB,CAAC,cAAA,EAAgB,MAAM,CAAC,CAAA;AAE/D,EAAA,MAAM,MAAA,GAASC,OAAY,IAAI,CAAA;AAE/B,EAAA,MAAA,CAAO,WAAW,MAAM,CAAA;AAExB,EAAA,WAAA,IAAe,KAAA,CAAM,IAAI,8BAA8B,CAAA;AAEvD,EAAA,OAAO,MAAA;AACT;;;;"}
1
+ {"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { applySdkMetadata, debug, setTag } from '@sentry/core';\nimport type { NodeClient, NodeOptions } from '@sentry/node';\nimport { getDefaultIntegrations as getNodeDefaultIntegrations, init as initNodeSdk } from '@sentry/node';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport { lowQualityTransactionsFilterIntegration } from './integration/lowQualityTransactionsFilterIntegration';\nimport { reactRouterServerIntegration } from './integration/reactRouterServer';\n\n/**\n * Returns the default integrations for the React Router SDK.\n * @param options The options for the SDK.\n */\nexport function getDefaultReactRouterServerIntegrations(options: NodeOptions): Integration[] {\n return [\n ...getNodeDefaultIntegrations(options),\n lowQualityTransactionsFilterIntegration(),\n reactRouterServerIntegration(),\n ];\n}\n\n/**\n * Initializes the server side of the React Router SDK\n */\nexport function init(options: NodeOptions): NodeClient | undefined {\n const opts: NodeOptions = {\n ...options,\n defaultIntegrations: getDefaultReactRouterServerIntegrations(options),\n };\n\n DEBUG_BUILD && debug.log('Initializing SDK...');\n\n applySdkMetadata(opts, 'react-router', ['react-router', 'node']);\n\n const client = initNodeSdk(opts);\n\n setTag('runtime', 'node');\n\n DEBUG_BUILD && debug.log('SDK successfully initialized');\n\n return client;\n}\n"],"names":["getNodeDefaultIntegrations","initNodeSdk"],"mappings":";;;;;;AAYO,SAAS,wCAAwC,OAAA,EAAqC;AAC3F,EAAA,OAAO;AAAA,IACL,GAAGA,uBAA2B,OAAO,CAAA;AAAA,IACrC,uCAAA,EAAwC;AAAA,IACxC,4BAAA;AAA6B,GAC/B;AACF;AAKO,SAAS,KAAK,OAAA,EAA8C;AACjE,EAAA,MAAM,IAAA,GAAoB;AAAA,IACxB,GAAG,OAAA;AAAA,IACH,mBAAA,EAAqB,wCAAwC,OAAO;AAAA,GACtE;AAEA,EAAA,WAAA,IAAe,KAAA,CAAM,IAAI,qBAAqB,CAAA;AAE9C,EAAA,gBAAA,CAAiB,IAAA,EAAM,cAAA,EAAgB,CAAC,cAAA,EAAgB,MAAM,CAAC,CAAA;AAE/D,EAAA,MAAM,MAAA,GAASC,OAAY,IAAI,CAAA;AAE/B,EAAA,MAAA,CAAO,WAAW,MAAM,CAAA;AAExB,EAAA,WAAA,IAAe,KAAA,CAAM,IAAI,8BAA8B,CAAA;AAEvD,EAAA,OAAO,MAAA;AACT;;;;"}
@@ -2,9 +2,6 @@ import { GLOBAL_OBJ } from '@sentry/core';
2
2
 
3
3
  const GLOBAL_KEY = "__sentrySetServerBuild";
4
4
  let _serverBuild;
5
- function isServerBuildLike(build) {
6
- return build !== null && typeof build === "object" && "routes" in build && build.routes !== null && typeof build.routes === "object";
7
- }
8
5
  function setServerBuild(build) {
9
6
  _serverBuild = build;
10
7
  }
@@ -19,5 +16,5 @@ function registerServerBuildGlobal() {
19
16
  GLOBAL_OBJ[GLOBAL_KEY] = setServerBuild;
20
17
  }
21
18
 
22
- export { GLOBAL_KEY, getMiddlewareName, isServerBuildLike, registerServerBuildGlobal, setServerBuild };
19
+ export { GLOBAL_KEY, getMiddlewareName, registerServerBuildGlobal, setServerBuild };
23
20
  //# sourceMappingURL=serverBuild.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"serverBuild.js","sources":["../../../src/server/serverBuild.ts"],"sourcesContent":["import { GLOBAL_OBJ } from '@sentry/core';\n\n/**\n * Subset of ServerBuild shape for middleware name lookup.\n * The official React Router types don't expose `middleware` on route modules yet.\n * @internal\n */\ninterface ServerBuildLike {\n routes?: Record<\n string,\n {\n module?: {\n middleware?: Array<{ name?: string }>;\n };\n }\n >;\n}\n\n/** @internal */\nexport const GLOBAL_KEY = '__sentrySetServerBuild';\n\ntype GlobalObjWithBuildCapture = typeof GLOBAL_OBJ & {\n [GLOBAL_KEY]?: (build: ServerBuildLike) => void;\n};\n\n// ServerBuild reference for middleware name lookup. Updated on each createRequestHandler call.\nlet _serverBuild: ServerBuildLike | undefined;\n\n/** @internal */\nexport function isServerBuildLike(build: unknown): build is ServerBuildLike {\n return (\n build !== null &&\n typeof build === 'object' &&\n 'routes' in build &&\n build.routes !== null &&\n typeof build.routes === 'object'\n );\n}\n\n/** @internal */\nexport function setServerBuild(build: ServerBuildLike): void {\n _serverBuild = build;\n}\n\n/** @internal */\nexport function getMiddlewareName(routeId: string, index: number): string | undefined {\n if (!_serverBuild?.routes) return undefined;\n\n const route = _serverBuild.routes[routeId];\n if (!route?.module?.middleware) return undefined;\n\n const middlewareFn = route.module.middleware[index];\n return middlewareFn?.name || undefined;\n}\n\n/** @internal */\nexport function registerServerBuildGlobal(): void {\n (GLOBAL_OBJ as GlobalObjWithBuildCapture)[GLOBAL_KEY] = setServerBuild;\n}\n\n/** @internal Exported for testing. */\nexport function _resetServerBuild(): void {\n _serverBuild = undefined;\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete (GLOBAL_OBJ as GlobalObjWithBuildCapture)[GLOBAL_KEY];\n}\n"],"names":[],"mappings":";;AAmBO,MAAM,UAAA,GAAa;AAO1B,IAAI,YAAA;AAGG,SAAS,kBAAkB,KAAA,EAA0C;AAC1E,EAAA,OACE,KAAA,KAAU,IAAA,IACV,OAAO,KAAA,KAAU,QAAA,IACjB,QAAA,IAAY,KAAA,IACZ,KAAA,CAAM,MAAA,KAAW,IAAA,IACjB,OAAO,KAAA,CAAM,MAAA,KAAW,QAAA;AAE5B;AAGO,SAAS,eAAe,KAAA,EAA8B;AAC3D,EAAA,YAAA,GAAe,KAAA;AACjB;AAGO,SAAS,iBAAA,CAAkB,SAAiB,KAAA,EAAmC;AACpF,EAAA,IAAI,CAAC,YAAA,EAAc,MAAA,EAAQ,OAAO,MAAA;AAElC,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,MAAA,CAAO,OAAO,CAAA;AACzC,EAAA,IAAI,CAAC,KAAA,EAAO,MAAA,EAAQ,UAAA,EAAY,OAAO,MAAA;AAEvC,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,MAAA,CAAO,UAAA,CAAW,KAAK,CAAA;AAClD,EAAA,OAAO,cAAc,IAAA,IAAQ,MAAA;AAC/B;AAGO,SAAS,yBAAA,GAAkC;AAChD,EAAC,UAAA,CAAyC,UAAU,CAAA,GAAI,cAAA;AAC1D;;;;"}
1
+ {"version":3,"file":"serverBuild.js","sources":["../../../src/server/serverBuild.ts"],"sourcesContent":["import { GLOBAL_OBJ } from '@sentry/core';\n\n/**\n * Subset of ServerBuild shape for middleware name lookup.\n * The official React Router types don't expose `middleware` on route modules yet.\n * @internal\n */\ninterface ServerBuildLike {\n routes?: Record<\n string,\n {\n module?: {\n middleware?: Array<{ name?: string }>;\n };\n }\n >;\n}\n\n/** @internal */\nexport const GLOBAL_KEY = '__sentrySetServerBuild';\n\ntype GlobalObjWithBuildCapture = typeof GLOBAL_OBJ & {\n [GLOBAL_KEY]?: (build: ServerBuildLike) => void;\n};\n\n// ServerBuild reference for middleware name lookup. Updated on each createRequestHandler call.\nlet _serverBuild: ServerBuildLike | undefined;\n\n/** @internal */\nexport function isServerBuildLike(build: unknown): build is ServerBuildLike {\n return (\n build !== null &&\n typeof build === 'object' &&\n 'routes' in build &&\n build.routes !== null &&\n typeof build.routes === 'object'\n );\n}\n\n/** @internal */\nexport function setServerBuild(build: ServerBuildLike): void {\n _serverBuild = build;\n}\n\n/** @internal */\nexport function getMiddlewareName(routeId: string, index: number): string | undefined {\n if (!_serverBuild?.routes) return undefined;\n\n const route = _serverBuild.routes[routeId];\n if (!route?.module?.middleware) return undefined;\n\n const middlewareFn = route.module.middleware[index];\n return middlewareFn?.name || undefined;\n}\n\n/** @internal */\nexport function registerServerBuildGlobal(): void {\n (GLOBAL_OBJ as GlobalObjWithBuildCapture)[GLOBAL_KEY] = setServerBuild;\n}\n\n/** @internal Exported for testing. */\nexport function _resetServerBuild(): void {\n _serverBuild = undefined;\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete (GLOBAL_OBJ as GlobalObjWithBuildCapture)[GLOBAL_KEY];\n}\n"],"names":[],"mappings":";;AAmBO,MAAM,UAAA,GAAa;AAO1B,IAAI,YAAA;AAcG,SAAS,eAAe,KAAA,EAA8B;AAC3D,EAAA,YAAA,GAAe,KAAA;AACjB;AAGO,SAAS,iBAAA,CAAkB,SAAiB,KAAA,EAAmC;AACpF,EAAA,IAAI,CAAC,YAAA,EAAc,MAAA,EAAQ,OAAO,MAAA;AAElC,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,MAAA,CAAO,OAAO,CAAA;AACzC,EAAA,IAAI,CAAC,KAAA,EAAO,MAAA,EAAQ,UAAA,EAAY,OAAO,MAAA;AAEvC,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,MAAA,CAAO,UAAA,CAAW,KAAK,CAAA;AAClD,EAAA,OAAO,cAAc,IAAA,IAAQ,MAAA;AAC/B;AAGO,SAAS,yBAAA,GAAkC;AAChD,EAAC,UAAA,CAAyC,UAAU,CAAA,GAAI,cAAA;AAC1D;;;;"}
@@ -1,19 +1,12 @@
1
1
  import { GLOBAL_OBJ } from '@sentry/core';
2
2
 
3
3
  const SENTRY_SERVER_INSTRUMENTATION_FLAG = "__sentryReactRouterServerInstrumentationUsed";
4
- const SENTRY_OTEL_SPAN_CREATION_FLAG = "__sentryReactRouterOtelSpanCreationEnabled";
5
4
  function markInstrumentationApiUsed() {
6
5
  GLOBAL_OBJ[SENTRY_SERVER_INSTRUMENTATION_FLAG] = true;
7
6
  }
8
7
  function isInstrumentationApiUsed() {
9
8
  return !!GLOBAL_OBJ[SENTRY_SERVER_INSTRUMENTATION_FLAG];
10
9
  }
11
- function enableOtelDataLoaderSpanCreation() {
12
- GLOBAL_OBJ[SENTRY_OTEL_SPAN_CREATION_FLAG] = true;
13
- }
14
- function isOtelDataLoaderSpanCreationEnabled() {
15
- return !!GLOBAL_OBJ[SENTRY_OTEL_SPAN_CREATION_FLAG];
16
- }
17
10
 
18
- export { enableOtelDataLoaderSpanCreation, isInstrumentationApiUsed, isOtelDataLoaderSpanCreationEnabled, markInstrumentationApiUsed };
11
+ export { isInstrumentationApiUsed, markInstrumentationApiUsed };
19
12
  //# sourceMappingURL=serverGlobals.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"serverGlobals.js","sources":["../../../src/server/serverGlobals.ts"],"sourcesContent":["import { GLOBAL_OBJ } from '@sentry/core';\n\nconst SENTRY_SERVER_INSTRUMENTATION_FLAG = '__sentryReactRouterServerInstrumentationUsed';\nconst SENTRY_OTEL_SPAN_CREATION_FLAG = '__sentryReactRouterOtelSpanCreationEnabled';\n\ntype GlobalObjWithFlag = typeof GLOBAL_OBJ & {\n [SENTRY_SERVER_INSTRUMENTATION_FLAG]?: boolean;\n [SENTRY_OTEL_SPAN_CREATION_FLAG]?: boolean;\n};\n\n/**\n * Mark that the React Router instrumentation API is being used on the server.\n * @internal\n */\nexport function markInstrumentationApiUsed(): void {\n (GLOBAL_OBJ as GlobalObjWithFlag)[SENTRY_SERVER_INSTRUMENTATION_FLAG] = true;\n}\n\n/**\n * Check if React Router's instrumentation API is being used on the server.\n */\nexport function isInstrumentationApiUsed(): boolean {\n return !!(GLOBAL_OBJ as GlobalObjWithFlag)[SENTRY_SERVER_INSTRUMENTATION_FLAG];\n}\n\n/**\n * Enable OTEL data-loader span creation for React Router server.\n * @internal\n */\nexport function enableOtelDataLoaderSpanCreation(): void {\n (GLOBAL_OBJ as GlobalObjWithFlag)[SENTRY_OTEL_SPAN_CREATION_FLAG] = true;\n}\n\n/**\n * Check if OTEL data-loader span creation is enabled for React Router server.\n * @internal\n */\nexport function isOtelDataLoaderSpanCreationEnabled(): boolean {\n return !!(GLOBAL_OBJ as GlobalObjWithFlag)[SENTRY_OTEL_SPAN_CREATION_FLAG];\n}\n"],"names":[],"mappings":";;AAEA,MAAM,kCAAA,GAAqC,8CAAA;AAC3C,MAAM,8BAAA,GAAiC,4CAAA;AAWhC,SAAS,0BAAA,GAAmC;AACjD,EAAC,UAAA,CAAiC,kCAAkC,CAAA,GAAI,IAAA;AAC1E;AAKO,SAAS,wBAAA,GAAoC;AAClD,EAAA,OAAO,CAAC,CAAE,UAAA,CAAiC,kCAAkC,CAAA;AAC/E;AAMO,SAAS,gCAAA,GAAyC;AACvD,EAAC,UAAA,CAAiC,8BAA8B,CAAA,GAAI,IAAA;AACtE;AAMO,SAAS,mCAAA,GAA+C;AAC7D,EAAA,OAAO,CAAC,CAAE,UAAA,CAAiC,8BAA8B,CAAA;AAC3E;;;;"}
1
+ {"version":3,"file":"serverGlobals.js","sources":["../../../src/server/serverGlobals.ts"],"sourcesContent":["import { GLOBAL_OBJ } from '@sentry/core';\n\nconst SENTRY_SERVER_INSTRUMENTATION_FLAG = '__sentryReactRouterServerInstrumentationUsed';\n\ntype GlobalObjWithFlag = typeof GLOBAL_OBJ & {\n [SENTRY_SERVER_INSTRUMENTATION_FLAG]?: boolean;\n};\n\n/**\n * Mark that the React Router instrumentation API is being used on the server.\n * @internal\n */\nexport function markInstrumentationApiUsed(): void {\n (GLOBAL_OBJ as GlobalObjWithFlag)[SENTRY_SERVER_INSTRUMENTATION_FLAG] = true;\n}\n\n/**\n * Check if React Router's instrumentation API is being used on the server.\n */\nexport function isInstrumentationApiUsed(): boolean {\n return !!(GLOBAL_OBJ as GlobalObjWithFlag)[SENTRY_SERVER_INSTRUMENTATION_FLAG];\n}\n"],"names":[],"mappings":";;AAEA,MAAM,kCAAA,GAAqC,8CAAA;AAUpC,SAAS,0BAAA,GAAmC;AACjD,EAAC,UAAA,CAAiC,kCAAkC,CAAA,GAAI,IAAA;AAC1E;AAKO,SAAS,wBAAA,GAAoC;AAClD,EAAA,OAAO,CAAC,CAAE,UAAA,CAAiC,kCAAkC,CAAA;AAC/E;;;;"}