@sentry/react 10.68.0 → 11.0.0-alpha.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.
- package/build/cjs/error.js +1 -7
- package/build/cjs/error.js.map +1 -1
- package/build/cjs/hoist-non-react-statics.js +1 -7
- package/build/cjs/hoist-non-react-statics.js.map +1 -1
- package/build/cjs/profiler.js +10 -6
- package/build/cjs/profiler.js.map +1 -1
- package/build/cjs/reactrouter-compat-utils/instrumentation.js +22 -24
- package/build/cjs/reactrouter-compat-utils/instrumentation.js.map +1 -1
- package/build/cjs/reactrouter.js +4 -1
- package/build/cjs/reactrouter.js.map +1 -1
- package/build/cjs/reactrouterv3.js.map +1 -1
- package/build/cjs/tanstackrouter.js +2 -1
- package/build/cjs/tanstackrouter.js.map +1 -1
- package/build/esm/error.js +2 -7
- package/build/esm/error.js.map +1 -1
- package/build/esm/hoist-non-react-statics.js +1 -7
- package/build/esm/hoist-non-react-statics.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/profiler.js +10 -6
- package/build/esm/profiler.js.map +1 -1
- package/build/esm/reactrouter-compat-utils/instrumentation.js +22 -24
- package/build/esm/reactrouter-compat-utils/instrumentation.js.map +1 -1
- package/build/esm/reactrouter.js +4 -1
- package/build/esm/reactrouter.js.map +1 -1
- package/build/esm/reactrouterv3.js.map +1 -1
- package/build/esm/tanstackrouter.js +2 -1
- package/build/esm/tanstackrouter.js.map +1 -1
- package/build/types/error.d.ts +0 -4
- package/build/types/error.d.ts.map +1 -1
- package/build/types/errorboundary.d.ts.map +1 -1
- package/build/types/hoist-non-react-statics.d.ts.map +1 -1
- package/build/types/profiler.d.ts +0 -1
- package/build/types/profiler.d.ts.map +1 -1
- package/build/types/reactrouter-compat-utils/instrumentation.d.ts +1 -1
- package/build/types/reactrouter-compat-utils/instrumentation.d.ts.map +1 -1
- package/build/types/reactrouter.d.ts.map +1 -1
- package/build/types/tanstackrouter.d.ts.map +1 -1
- package/package.json +8 -19
- package/build/cjs/constants.js +0 -10
- package/build/cjs/constants.js.map +0 -1
- package/build/esm/constants.js +0 -6
- package/build/esm/constants.js.map +0 -1
- package/build/types/constants.d.ts +0 -4
- package/build/types/constants.d.ts.map +0 -1
- package/build/types-ts3.8/constants.d.ts +0 -4
- package/build/types-ts3.8/debug-build.d.ts +0 -7
- package/build/types-ts3.8/error.d.ts +0 -41
- package/build/types-ts3.8/errorboundary.d.ts +0 -87
- package/build/types-ts3.8/hoist-non-react-statics.d.ts +0 -21
- package/build/types-ts3.8/index.d.ts +0 -14
- package/build/types-ts3.8/isSyntheticEvent.d.ts +0 -10
- package/build/types-ts3.8/profiler.d.ts +0 -56
- package/build/types-ts3.8/reactrouter-compat-utils/index.d.ts +0 -5
- package/build/types-ts3.8/reactrouter-compat-utils/instrumentation.d.ts +0 -117
- package/build/types-ts3.8/reactrouter-compat-utils/lazy-routes.d.ts +0 -18
- package/build/types-ts3.8/reactrouter-compat-utils/route-manifest.d.ts +0 -13
- package/build/types-ts3.8/reactrouter-compat-utils/utils.d.ts +0 -77
- package/build/types-ts3.8/reactrouter.compat.d.ts +0 -42
- package/build/types-ts3.8/reactrouter.d.ts +0 -41
- package/build/types-ts3.8/reactrouterv3.d.ts +0 -29
- package/build/types-ts3.8/reactrouterv6.d.ts +0 -42
- package/build/types-ts3.8/reactrouterv7.d.ts +0 -42
- package/build/types-ts3.8/redux.d.ts +0 -38
- package/build/types-ts3.8/sdk.d.ts +0 -7
- package/build/types-ts3.8/tanstackrouter.d.ts +0 -13
- package/build/types-ts3.8/types.d.ts +0 -163
- package/build/types-ts3.8/vendor/tanstackrouter-types.d.ts +0 -37
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tanstackrouter.js","sources":["../../src/tanstackrouter.ts"],"sourcesContent":["import {\n browserTracingIntegration as originalBrowserTracingIntegration,\n getAbsoluteUrl,\n startBrowserTracingNavigationSpan,\n startBrowserTracingPageLoadSpan,\n WINDOW,\n} from '@sentry/browser';\nimport type { Integration } from '@sentry/core/browser';\nimport {\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n} from '@sentry/core/browser';\nimport type { VendoredTanstackRouter, VendoredTanstackRouterRouteMatch } from './vendor/tanstackrouter-types';\nimport {\n PARAMS_KEY_BASE,\n URL_FULL,\n URL_PATH,\n URL_PATH_PARAMETER_KEY_BASE,\n URL_TEMPLATE,\n} from '@sentry/conventions/attributes';\n\ninterface TanstackRouterLocation {\n pathname: string;\n search: Record<string, unknown>;\n state?: unknown;\n}\n\n/**\n * A custom browser tracing integration for TanStack Router.\n *\n * The minimum compatible version of `@tanstack/react-router` is `1.64.0`.\n *\n * @param router A TanStack Router `Router` instance that should be used for routing instrumentation.\n * @param options Sentry browser tracing configuration.\n */\nexport function tanstackRouterBrowserTracingIntegration(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n router: any, // This is `any` because we don't want any type mismatches if TanStack Router changes their types\n options: Parameters<typeof originalBrowserTracingIntegration>[0] = {},\n): Integration {\n const castRouterInstance: VendoredTanstackRouter = router;\n\n const browserTracingIntegrationInstance = originalBrowserTracingIntegration({\n ...options,\n instrumentNavigation: false,\n instrumentPageLoad: false,\n });\n\n const { instrumentPageLoad = true, instrumentNavigation = true } = options;\n\n return {\n ...browserTracingIntegrationInstance,\n afterAllSetup(client) {\n browserTracingIntegrationInstance.afterAllSetup(client);\n\n const resolveRouteMatch = (pathname: string, search: unknown): VendoredTanstackRouterRouteMatch | undefined => {\n const matchedRoutes = castRouterInstance.matchRoutes(pathname, search as {}, {\n preload: false,\n throwOnError: false,\n });\n const lastMatch = matchedRoutes[matchedRoutes.length - 1];\n // If we only match __root__, we ended up not matching any route at all, so\n // we fall back to the pathname.\n return lastMatch?.routeId !== '__root__' ? lastMatch : undefined;\n };\n\n const applyRouteMatch = (\n span: NonNullable<ReturnType<typeof startBrowserTracingPageLoadSpan>>,\n match: VendoredTanstackRouterRouteMatch | undefined,\n toLocation: TanstackRouterLocation,\n fallbackName: string,\n ): void => {\n span.updateName(match ? match.routeId : fallbackName);\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, match ? 'route' : 'url');\n span.setAttributes({\n ...(match && { [URL_TEMPLATE]: match.routeId }),\n ...locationToSpanUrlAttributes(castRouterInstance, toLocation),\n ...routeMatchToParamSpanAttributes(match),\n });\n };\n\n const initialWindowLocation = WINDOW.location;\n if (instrumentPageLoad && initialWindowLocation) {\n const routeMatch = resolveRouteMatch(\n initialWindowLocation.pathname,\n castRouterInstance.options.parseSearch(initialWindowLocation.search),\n );\n\n const pageloadSpan = startBrowserTracingPageLoadSpan(client, {\n name: routeMatch ? routeMatch.routeId : initialWindowLocation.pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.react.tanstack_router',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: routeMatch ? 'route' : 'url',\n ...(routeMatch && { [URL_TEMPLATE]: routeMatch.routeId }),\n ...routeMatchToParamSpanAttributes(routeMatch),\n },\n });\n\n // A redirect thrown during the initial pageload leaves the span named after the pre-redirect\n // route, so correct it to the resolved route once.\n const unsubscribePageloadResolved = castRouterInstance.subscribe('onResolved', onResolvedArgs => {\n unsubscribePageloadResolved();\n if (!pageloadSpan) {\n return;\n }\n const { toLocation } = onResolvedArgs;\n const resolvedMatch = resolveRouteMatch(toLocation.pathname, toLocation.search);\n applyRouteMatch(pageloadSpan, resolvedMatch, toLocation, toLocation.pathname);\n });\n }\n\n if (instrumentNavigation) {\n // Navigation is driven by `onBeforeLoad` (accurate start) + `onResolved` (final route), not\n // `onBeforeNavigate`, which TanStack stops firing after any loader redirect (TanStack/router#3920).\n // A redirect chain emits one `onBeforeLoad` per load but a single `onResolved`, so we start the\n // span on the first `onBeforeLoad`, rename it on later ones, and clear it on `onResolved`.\n let inFlightNavigationSpan: ReturnType<typeof startBrowserTracingNavigationSpan> | undefined;\n\n castRouterInstance.subscribe('onBeforeLoad', onBeforeLoadArgs => {\n const { toLocation, fromLocation } = onBeforeLoadArgs;\n // Skip the initial pageload (no fromLocation) and no-op reloads (same state).\n if (!fromLocation || toLocation.state === fromLocation.state) {\n return;\n }\n\n const routeMatch = resolveRouteMatch(toLocation.pathname, toLocation.search);\n const fallbackName = WINDOW.location?.pathname || toLocation.pathname;\n\n if (inFlightNavigationSpan) {\n // Redirect continuation within the same navigation: keep the span, update the target.\n applyRouteMatch(inFlightNavigationSpan, routeMatch, toLocation, fallbackName);\n return;\n }\n\n inFlightNavigationSpan = startBrowserTracingNavigationSpan(\n client,\n {\n name: routeMatch ? routeMatch.routeId : fallbackName,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react.tanstack_router',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: routeMatch ? 'route' : 'url',\n ...(routeMatch && { [URL_TEMPLATE]: routeMatch.routeId }),\n ...routeMatchToParamSpanAttributes(routeMatch),\n },\n },\n { url: locationToAbsoluteUrl(castRouterInstance, toLocation) },\n );\n });\n\n castRouterInstance.subscribe('onResolved', onResolvedArgs => {\n const span = inFlightNavigationSpan;\n inFlightNavigationSpan = undefined;\n if (!span) {\n return;\n }\n const { toLocation } = onResolvedArgs;\n const resolvedMatch = resolveRouteMatch(toLocation.pathname, toLocation.search);\n if (resolvedMatch) {\n applyRouteMatch(span, resolvedMatch, toLocation, WINDOW.location?.pathname || toLocation.pathname);\n }\n });\n }\n },\n };\n}\n\nfunction locationToAbsoluteUrl(router: VendoredTanstackRouter, location: TanstackRouterLocation): string {\n const search = router.options.stringifySearch?.(location.search) ?? '';\n const pathWithSearch = `${location.pathname}${search && search !== '?' ? search : ''}`;\n\n return getAbsoluteUrl(pathWithSearch);\n}\n\nfunction locationToSpanUrlAttributes(\n router: VendoredTanstackRouter,\n location: TanstackRouterLocation,\n): Record<string, string> {\n const absoluteUrl = locationToAbsoluteUrl(router, location);\n\n return {\n [URL_PATH]: location.pathname,\n [URL_FULL]: absoluteUrl,\n };\n}\n\nfunction routeMatchToParamSpanAttributes(match: VendoredTanstackRouterRouteMatch | undefined): Record<string, string> {\n if (!match) {\n return {};\n }\n\n const paramAttributes: Record<string, string> = {};\n Object.entries(match.params).forEach(([key, value]) => {\n paramAttributes[`url.path.params.${key}`] = value; // TODO(v11): remove attribute which does not adhere to Sentry's semantic convention\n paramAttributes[`${URL_PATH_PARAMETER_KEY_BASE}.${key}`] = value;\n paramAttributes[`${PARAMS_KEY_BASE}.${key}`] = value; // params.[key] is an alias\n });\n\n return paramAttributes;\n}\n"],"names":["originalBrowserTracingIntegration","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","URL_TEMPLATE","WINDOW","startBrowserTracingPageLoadSpan","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","startBrowserTracingNavigationSpan","getAbsoluteUrl","URL_PATH","URL_FULL","URL_PATH_PARAMETER_KEY_BASE","PARAMS_KEY_BASE"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tanstackrouter.js","sources":["../../src/tanstackrouter.ts"],"sourcesContent":["import {\n browserTracingIntegration as originalBrowserTracingIntegration,\n getAbsoluteUrl,\n startBrowserTracingNavigationSpan,\n startBrowserTracingPageLoadSpan,\n WINDOW,\n} from '@sentry/browser';\nimport type { Integration } from '@sentry/core/browser';\nimport { filterCollectedUrl } from '@sentry/core';\nimport {\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n} from '@sentry/core/browser';\nimport type { VendoredTanstackRouter, VendoredTanstackRouterRouteMatch } from './vendor/tanstackrouter-types';\nimport {\n PARAMS_KEY_BASE,\n URL_FULL,\n URL_PATH,\n URL_PATH_PARAMETER_KEY_BASE,\n URL_TEMPLATE,\n} from '@sentry/conventions/attributes';\n\ninterface TanstackRouterLocation {\n pathname: string;\n search: Record<string, unknown>;\n state?: unknown;\n}\n\n/**\n * A custom browser tracing integration for TanStack Router.\n *\n * The minimum compatible version of `@tanstack/react-router` is `1.64.0`.\n *\n * @param router A TanStack Router `Router` instance that should be used for routing instrumentation.\n * @param options Sentry browser tracing configuration.\n */\nexport function tanstackRouterBrowserTracingIntegration(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n router: any, // This is `any` because we don't want any type mismatches if TanStack Router changes their types\n options: Parameters<typeof originalBrowserTracingIntegration>[0] = {},\n): Integration {\n const castRouterInstance: VendoredTanstackRouter = router;\n\n const browserTracingIntegrationInstance = originalBrowserTracingIntegration({\n ...options,\n instrumentNavigation: false,\n instrumentPageLoad: false,\n });\n\n const { instrumentPageLoad = true, instrumentNavigation = true } = options;\n\n return {\n ...browserTracingIntegrationInstance,\n afterAllSetup(client) {\n browserTracingIntegrationInstance.afterAllSetup(client);\n\n const resolveRouteMatch = (pathname: string, search: unknown): VendoredTanstackRouterRouteMatch | undefined => {\n const matchedRoutes = castRouterInstance.matchRoutes(pathname, search as {}, {\n preload: false,\n throwOnError: false,\n });\n const lastMatch = matchedRoutes[matchedRoutes.length - 1];\n // If we only match __root__, we ended up not matching any route at all, so\n // we fall back to the pathname.\n return lastMatch?.routeId !== '__root__' ? lastMatch : undefined;\n };\n\n const applyRouteMatch = (\n span: NonNullable<ReturnType<typeof startBrowserTracingPageLoadSpan>>,\n match: VendoredTanstackRouterRouteMatch | undefined,\n toLocation: TanstackRouterLocation,\n fallbackName: string,\n ): void => {\n span.updateName(match ? match.routeId : fallbackName);\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, match ? 'route' : 'url');\n span.setAttributes({\n ...(match && { [URL_TEMPLATE]: match.routeId }),\n ...locationToSpanUrlAttributes(castRouterInstance, toLocation),\n ...routeMatchToParamSpanAttributes(match),\n });\n };\n\n const initialWindowLocation = WINDOW.location;\n if (instrumentPageLoad && initialWindowLocation) {\n const routeMatch = resolveRouteMatch(\n initialWindowLocation.pathname,\n castRouterInstance.options.parseSearch(initialWindowLocation.search),\n );\n\n const pageloadSpan = startBrowserTracingPageLoadSpan(client, {\n name: routeMatch ? routeMatch.routeId : initialWindowLocation.pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.react.tanstack_router',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: routeMatch ? 'route' : 'url',\n ...(routeMatch && { [URL_TEMPLATE]: routeMatch.routeId }),\n ...routeMatchToParamSpanAttributes(routeMatch),\n },\n });\n\n // A redirect thrown during the initial pageload leaves the span named after the pre-redirect\n // route, so correct it to the resolved route once.\n const unsubscribePageloadResolved = castRouterInstance.subscribe('onResolved', onResolvedArgs => {\n unsubscribePageloadResolved();\n if (!pageloadSpan) {\n return;\n }\n const { toLocation } = onResolvedArgs;\n const resolvedMatch = resolveRouteMatch(toLocation.pathname, toLocation.search);\n applyRouteMatch(pageloadSpan, resolvedMatch, toLocation, toLocation.pathname);\n });\n }\n\n if (instrumentNavigation) {\n // Navigation is driven by `onBeforeLoad` (accurate start) + `onResolved` (final route), not\n // `onBeforeNavigate`, which TanStack stops firing after any loader redirect (TanStack/router#3920).\n // A redirect chain emits one `onBeforeLoad` per load but a single `onResolved`, so we start the\n // span on the first `onBeforeLoad`, rename it on later ones, and clear it on `onResolved`.\n let inFlightNavigationSpan: ReturnType<typeof startBrowserTracingNavigationSpan> | undefined;\n\n castRouterInstance.subscribe('onBeforeLoad', onBeforeLoadArgs => {\n const { toLocation, fromLocation } = onBeforeLoadArgs;\n // Skip the initial pageload (no fromLocation) and no-op reloads (same state).\n if (!fromLocation || toLocation.state === fromLocation.state) {\n return;\n }\n\n const routeMatch = resolveRouteMatch(toLocation.pathname, toLocation.search);\n const fallbackName = WINDOW.location?.pathname || toLocation.pathname;\n\n if (inFlightNavigationSpan) {\n // Redirect continuation within the same navigation: keep the span, update the target.\n applyRouteMatch(inFlightNavigationSpan, routeMatch, toLocation, fallbackName);\n return;\n }\n\n inFlightNavigationSpan = startBrowserTracingNavigationSpan(\n client,\n {\n name: routeMatch ? routeMatch.routeId : fallbackName,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react.tanstack_router',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: routeMatch ? 'route' : 'url',\n ...(routeMatch && { [URL_TEMPLATE]: routeMatch.routeId }),\n ...routeMatchToParamSpanAttributes(routeMatch),\n },\n },\n { url: locationToAbsoluteUrl(castRouterInstance, toLocation) },\n );\n });\n\n castRouterInstance.subscribe('onResolved', onResolvedArgs => {\n const span = inFlightNavigationSpan;\n inFlightNavigationSpan = undefined;\n if (!span) {\n return;\n }\n const { toLocation } = onResolvedArgs;\n const resolvedMatch = resolveRouteMatch(toLocation.pathname, toLocation.search);\n if (resolvedMatch) {\n applyRouteMatch(span, resolvedMatch, toLocation, WINDOW.location?.pathname || toLocation.pathname);\n }\n });\n }\n },\n };\n}\n\nfunction locationToAbsoluteUrl(router: VendoredTanstackRouter, location: TanstackRouterLocation): string {\n const search = router.options.stringifySearch?.(location.search) ?? '';\n const pathWithSearch = `${location.pathname}${search && search !== '?' ? search : ''}`;\n\n return getAbsoluteUrl(pathWithSearch);\n}\n\nfunction locationToSpanUrlAttributes(\n router: VendoredTanstackRouter,\n location: TanstackRouterLocation,\n): Record<string, string> {\n const absoluteUrl = locationToAbsoluteUrl(router, location);\n\n return {\n [URL_PATH]: location.pathname,\n [URL_FULL]: filterCollectedUrl(absoluteUrl),\n };\n}\n\nfunction routeMatchToParamSpanAttributes(match: VendoredTanstackRouterRouteMatch | undefined): Record<string, string> {\n if (!match) {\n return {};\n }\n\n const paramAttributes: Record<string, string> = {};\n Object.entries(match.params).forEach(([key, value]) => {\n paramAttributes[`url.path.params.${key}`] = value; // TODO(v11): remove attribute which does not adhere to Sentry's semantic convention\n paramAttributes[`${URL_PATH_PARAMETER_KEY_BASE}.${key}`] = value;\n paramAttributes[`${PARAMS_KEY_BASE}.${key}`] = value; // params.[key] is an alias\n });\n\n return paramAttributes;\n}\n"],"names":["originalBrowserTracingIntegration","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","URL_TEMPLATE","WINDOW","startBrowserTracingPageLoadSpan","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","startBrowserTracingNavigationSpan","getAbsoluteUrl","URL_PATH","URL_FULL","filterCollectedUrl","URL_PATH_PARAMETER_KEY_BASE","PARAMS_KEY_BASE"],"mappings":"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"}
|
package/build/esm/error.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { captureException } from '@sentry/browser';
|
|
2
2
|
import { isError } from '@sentry/core/browser';
|
|
3
|
-
import { version } from 'react';
|
|
4
3
|
|
|
5
|
-
function isAtLeastReact17(reactVersion) {
|
|
6
|
-
const reactMajor = reactVersion.match(/^([^.]+)/);
|
|
7
|
-
return reactMajor !== null && parseInt(reactMajor[0]) >= 17;
|
|
8
|
-
}
|
|
9
4
|
function setCause(error, cause) {
|
|
10
5
|
const seenErrors = /* @__PURE__ */ new WeakSet();
|
|
11
6
|
function recurse(error2, cause2) {
|
|
@@ -21,7 +16,7 @@ function setCause(error, cause) {
|
|
|
21
16
|
recurse(error, cause);
|
|
22
17
|
}
|
|
23
18
|
function captureReactException(error, { componentStack }, hint) {
|
|
24
|
-
if (
|
|
19
|
+
if (isError(error) && componentStack) {
|
|
25
20
|
const errorBoundaryError = new Error(error.message);
|
|
26
21
|
errorBoundaryError.name = `React ErrorBoundary ${error.name}`;
|
|
27
22
|
errorBoundaryError.stack = componentStack;
|
|
@@ -41,5 +36,5 @@ function reactErrorHandler(callback) {
|
|
|
41
36
|
};
|
|
42
37
|
}
|
|
43
38
|
|
|
44
|
-
export { captureReactException,
|
|
39
|
+
export { captureReactException, reactErrorHandler, setCause };
|
|
45
40
|
//# sourceMappingURL=error.js.map
|
package/build/esm/error.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","sources":["../../src/error.ts"],"sourcesContent":["import { captureException } from '@sentry/browser';\nimport { isError } from '@sentry/core/browser';\nimport type { ErrorInfo } from 'react';\
|
|
1
|
+
{"version":3,"file":"error.js","sources":["../../src/error.ts"],"sourcesContent":["import { captureException } from '@sentry/browser';\nimport { isError } from '@sentry/core/browser';\nimport type { ErrorInfo } from 'react';\n\n/**\n * Recurse through `error.cause` chain to set cause on an error.\n */\nexport function setCause(error: Error & { cause?: Error }, cause: Error): void {\n const seenErrors = new WeakSet();\n\n function recurse(error: Error & { cause?: Error }, cause: Error): void {\n // If we've already seen the error, there is a recursive loop somewhere in the error's\n // cause chain. Let's just bail out then to prevent a stack overflow.\n if (seenErrors.has(error)) {\n return;\n }\n if (error.cause) {\n seenErrors.add(error);\n return recurse(error.cause, cause);\n }\n error.cause = cause;\n }\n\n recurse(error, cause);\n}\n\n/**\n * Captures an error that was thrown by a React ErrorBoundary or React root.\n *\n * @param error The error to capture.\n * @param errorInfo The errorInfo provided by React.\n * @param hint Optional additional data to attach to the Sentry event.\n * @returns the id of the captured Sentry event.\n */\nexport function captureReactException(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error: any,\n { componentStack }: ErrorInfo,\n hint?: Parameters<typeof captureException>[1],\n): string {\n // Create a stack trace from the componentStack param and link it to the original error\n // using `error.cause`. Linking errors requires the `LinkedErrors` integration be enabled.\n // See: https://reactjs.org/blog/2020/08/10/react-v17-rc.html#native-component-stacks\n //\n // Although `componentDidCatch` is typed to accept an `Error` object, it can also be invoked\n // with non-error objects. This is why we need to check if the error is an error-like object.\n // See: https://github.com/getsentry/sentry-javascript/issues/6167\n if (isError(error) && componentStack) {\n const errorBoundaryError = new Error(error.message);\n errorBoundaryError.name = `React ErrorBoundary ${error.name}`;\n errorBoundaryError.stack = componentStack;\n\n // Using the `LinkedErrors` integration to link the errors together.\n setCause(error, errorBoundaryError);\n }\n\n return captureException(error, hint);\n}\n\n/**\n * Creates an error handler that can be used with the `onCaughtError`, `onUncaughtError`,\n * and `onRecoverableError` options in `createRoot` and `hydrateRoot` React DOM methods.\n *\n * @param callback An optional callback that will be called after the error is captured.\n * Use this to add custom handling for errors.\n *\n * @example\n *\n * ```JavaScript\n * const root = createRoot(container, {\n * onCaughtError: Sentry.reactErrorHandler(),\n * onUncaughtError: Sentry.reactErrorHandler((error, errorInfo) => {\n * console.warn('Caught error', error, errorInfo.componentStack);\n * });\n * });\n * ```\n */\nexport function reactErrorHandler(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n callback?: (error: any, errorInfo: ErrorInfo, eventId: string) => void,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): (error: any, errorInfo: ErrorInfo) => void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (error: any, errorInfo: ErrorInfo) => {\n const hasCallback = !!callback;\n const eventId = captureReactException(error, errorInfo, {\n mechanism: { handled: hasCallback, type: 'auto.function.react.error_handler' },\n });\n if (hasCallback) {\n callback(error, errorInfo, eventId);\n }\n };\n}\n"],"names":["error","cause"],"mappings":";;;AAOO,SAAS,QAAA,CAAS,OAAkC,KAAA,EAAoB;AAC7E,EAAA,MAAM,UAAA,uBAAiB,OAAA,EAAQ;AAE/B,EAAA,SAAS,OAAA,CAAQA,QAAkCC,MAAAA,EAAoB;AAGrE,IAAA,IAAI,UAAA,CAAW,GAAA,CAAID,MAAK,CAAA,EAAG;AACzB,MAAA;AAAA,IACF;AACA,IAAA,IAAIA,OAAM,KAAA,EAAO;AACf,MAAA,UAAA,CAAW,IAAIA,MAAK,CAAA;AACpB,MAAA,OAAO,OAAA,CAAQA,MAAAA,CAAM,KAAA,EAAOC,MAAK,CAAA;AAAA,IACnC;AACA,IAAAD,OAAM,KAAA,GAAQC,MAAAA;AAAA,EAChB;AAEA,EAAA,OAAA,CAAQ,OAAO,KAAK,CAAA;AACtB;AAUO,SAAS,qBAAA,CAEd,KAAA,EACA,EAAE,cAAA,IACF,IAAA,EACQ;AAQR,EAAA,IAAI,OAAA,CAAQ,KAAK,CAAA,IAAK,cAAA,EAAgB;AACpC,IAAA,MAAM,kBAAA,GAAqB,IAAI,KAAA,CAAM,KAAA,CAAM,OAAO,CAAA;AAClD,IAAA,kBAAA,CAAmB,IAAA,GAAO,CAAA,oBAAA,EAAuB,KAAA,CAAM,IAAI,CAAA,CAAA;AAC3D,IAAA,kBAAA,CAAmB,KAAA,GAAQ,cAAA;AAG3B,IAAA,QAAA,CAAS,OAAO,kBAAkB,CAAA;AAAA,EACpC;AAEA,EAAA,OAAO,gBAAA,CAAiB,OAAO,IAAI,CAAA;AACrC;AAoBO,SAAS,kBAEd,QAAA,EAE4C;AAE5C,EAAA,OAAO,CAAC,OAAY,SAAA,KAAyB;AAC3C,IAAA,MAAM,WAAA,GAAc,CAAC,CAAC,QAAA;AACtB,IAAA,MAAM,OAAA,GAAU,qBAAA,CAAsB,KAAA,EAAO,SAAA,EAAW;AAAA,MACtD,SAAA,EAAW,EAAE,OAAA,EAAS,WAAA,EAAa,MAAM,mCAAA;AAAoC,KAC9E,CAAA;AACD,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,QAAA,CAAS,KAAA,EAAO,WAAW,OAAO,CAAA;AAAA,IACpC;AAAA,EACF,CAAA;AACF;;;;"}
|
|
@@ -37,16 +37,10 @@ const MEMO_STATICS = {
|
|
|
37
37
|
};
|
|
38
38
|
const ForwardRefType = /* @__PURE__ */ Symbol.for("react.forward_ref");
|
|
39
39
|
const MemoType = /* @__PURE__ */ Symbol.for("react.memo");
|
|
40
|
-
function isMemo(component) {
|
|
41
|
-
return typeof component === "object" && component !== null && component.$$typeof === MemoType;
|
|
42
|
-
}
|
|
43
40
|
const TYPE_STATICS = {};
|
|
44
41
|
TYPE_STATICS[ForwardRefType] = FORWARD_REF_STATICS;
|
|
45
42
|
TYPE_STATICS[MemoType] = MEMO_STATICS;
|
|
46
43
|
function getStatics(component) {
|
|
47
|
-
if (isMemo(component)) {
|
|
48
|
-
return MEMO_STATICS;
|
|
49
|
-
}
|
|
50
44
|
const componentType = component.$$typeof;
|
|
51
45
|
return componentType && TYPE_STATICS[componentType] || REACT_STATICS;
|
|
52
46
|
}
|
|
@@ -76,7 +70,7 @@ function hoistNonReactStatics(targetComponent, sourceComponent, excludelist) {
|
|
|
76
70
|
if (descriptor) {
|
|
77
71
|
try {
|
|
78
72
|
defineProperty(targetComponent, key, descriptor);
|
|
79
|
-
} catch
|
|
73
|
+
} catch {
|
|
80
74
|
}
|
|
81
75
|
}
|
|
82
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hoist-non-react-statics.js","sources":["../../src/hoist-non-react-statics.ts"],"sourcesContent":["/**\n * Inlined implementation of hoist-non-react-statics\n * Original library: https://github.com/mridgway/hoist-non-react-statics\n * License: BSD-3-Clause\n * Copyright 2015, Yahoo! Inc.\n *\n * This is an inlined version to avoid ESM compatibility issues with the original package.\n */\n\nimport type * as React from 'react';\n\n/**\n * React statics that should not be hoisted\n */\nconst REACT_STATICS = {\n childContextTypes: true,\n contextType: true,\n contextTypes: true,\n defaultProps: true,\n displayName: true,\n getDefaultProps: true,\n getDerivedStateFromError: true,\n getDerivedStateFromProps: true,\n mixins: true,\n propTypes: true,\n type: true,\n} as const;\n\n/**\n * Known JavaScript function statics that should not be hoisted\n */\nconst KNOWN_STATICS = {\n name: true,\n length: true,\n prototype: true,\n caller: true,\n callee: true,\n arguments: true,\n arity: true,\n} as const;\n\n/**\n * Statics specific to ForwardRef components\n */\nconst FORWARD_REF_STATICS = {\n $$typeof: true,\n render: true,\n defaultProps: true,\n displayName: true,\n propTypes: true,\n} as const;\n\n/**\n * Statics specific to Memo components\n */\nconst MEMO_STATICS = {\n $$typeof: true,\n compare: true,\n defaultProps: true,\n displayName: true,\n propTypes: true,\n type: true,\n} as const;\n\n/**\n * Inlined react-is utilities\n * We only need to detect ForwardRef and Memo types\n */\nconst ForwardRefType = Symbol.for('react.forward_ref');\nconst MemoType = Symbol.for('react.memo');\n\n/**\n *
|
|
1
|
+
{"version":3,"file":"hoist-non-react-statics.js","sources":["../../src/hoist-non-react-statics.ts"],"sourcesContent":["/**\n * Inlined implementation of hoist-non-react-statics\n * Original library: https://github.com/mridgway/hoist-non-react-statics\n * License: BSD-3-Clause\n * Copyright 2015, Yahoo! Inc.\n *\n * This is an inlined version to avoid ESM compatibility issues with the original package.\n */\n\nimport type * as React from 'react';\n\n/**\n * React statics that should not be hoisted\n */\nconst REACT_STATICS = {\n childContextTypes: true,\n contextType: true,\n contextTypes: true,\n defaultProps: true,\n displayName: true,\n getDefaultProps: true,\n getDerivedStateFromError: true,\n getDerivedStateFromProps: true,\n mixins: true,\n propTypes: true,\n type: true,\n} as const;\n\n/**\n * Known JavaScript function statics that should not be hoisted\n */\nconst KNOWN_STATICS = {\n name: true,\n length: true,\n prototype: true,\n caller: true,\n callee: true,\n arguments: true,\n arity: true,\n} as const;\n\n/**\n * Statics specific to ForwardRef components\n */\nconst FORWARD_REF_STATICS = {\n $$typeof: true,\n render: true,\n defaultProps: true,\n displayName: true,\n propTypes: true,\n} as const;\n\n/**\n * Statics specific to Memo components\n */\nconst MEMO_STATICS = {\n $$typeof: true,\n compare: true,\n defaultProps: true,\n displayName: true,\n propTypes: true,\n type: true,\n} as const;\n\n/**\n * Inlined react-is utilities\n * We only need to detect ForwardRef and Memo types\n */\nconst ForwardRefType = Symbol.for('react.forward_ref');\nconst MemoType = Symbol.for('react.memo');\n\n/**\n * Map of React component types to their specific statics\n */\nconst TYPE_STATICS: Record<symbol, Record<string, boolean>> = {};\nTYPE_STATICS[ForwardRefType] = FORWARD_REF_STATICS;\nTYPE_STATICS[MemoType] = MEMO_STATICS;\n\n/**\n * Get the appropriate statics object for a given component\n */\nfunction getStatics(component: React.ComponentType<unknown>): Record<string, boolean> {\n const componentType = (component as { $$typeof?: symbol }).$$typeof;\n return (componentType && TYPE_STATICS[componentType]) || REACT_STATICS;\n}\n\nconst defineProperty = Object.defineProperty.bind(Object);\nconst getOwnPropertyNames = Object.getOwnPropertyNames.bind(Object);\nconst getOwnPropertySymbols = Object.getOwnPropertySymbols?.bind(Object);\nconst getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor.bind(Object);\nconst getPrototypeOf = Object.getPrototypeOf.bind(Object);\nconst objectPrototype = Object.prototype;\n\n/**\n * Copies non-react specific statics from a child component to a parent component.\n * Similar to Object.assign, but copies all static properties from source to target,\n * excluding React-specific statics and known JavaScript statics.\n *\n * @param targetComponent - The component to copy statics to\n * @param sourceComponent - The component to copy statics from\n * @param excludelist - An optional object of keys to exclude from hoisting\n * @returns The target component with hoisted statics\n */\nexport function hoistNonReactStatics<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n T extends React.ComponentType<any>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n S extends React.ComponentType<any>,\n C extends Record<string, boolean> = Record<string, never>,\n>(targetComponent: T, sourceComponent: S, excludelist?: C): T {\n if (typeof sourceComponent !== 'string') {\n // Don't hoist over string (html) components\n if (objectPrototype) {\n const inheritedComponent = getPrototypeOf(sourceComponent);\n\n if (inheritedComponent && inheritedComponent !== objectPrototype) {\n hoistNonReactStatics(targetComponent, inheritedComponent, excludelist);\n }\n }\n\n let keys: (string | symbol)[] = getOwnPropertyNames(sourceComponent);\n\n if (getOwnPropertySymbols) {\n keys = keys.concat(getOwnPropertySymbols(sourceComponent));\n }\n\n const targetStatics = getStatics(targetComponent);\n const sourceStatics = getStatics(sourceComponent);\n\n for (const key of keys) {\n // Use key directly - String(key) throws for Symbols if minified to '' + key (#18966)\n if (\n !KNOWN_STATICS[key as keyof typeof KNOWN_STATICS] &&\n !excludelist?.[key as keyof C] &&\n !sourceStatics?.[key as string] &&\n !targetStatics?.[key as string] &&\n !getOwnPropertyDescriptor(targetComponent, key) // Don't overwrite existing properties\n ) {\n const descriptor = getOwnPropertyDescriptor(sourceComponent, key);\n\n if (descriptor) {\n try {\n // Avoid failures from read-only properties\n defineProperty(targetComponent, key, descriptor);\n } catch {\n // Silently ignore errors\n }\n }\n }\n }\n }\n\n return targetComponent;\n}\n"],"names":[],"mappings":"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"}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"
|
|
1
|
+
{"type":"module","version":"11.0.0-alpha.0","sideEffects":false}
|
package/build/esm/profiler.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { startInactiveSpan } from '@sentry/browser';
|
|
2
2
|
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, timestampInSeconds, withActiveSpan, spanToJSON } from '@sentry/core';
|
|
3
|
+
import { SENTRY_OP } from '@sentry/conventions/attributes';
|
|
4
|
+
import { BROWSER_UI_RENDER_SPAN_OP } from '@sentry/conventions/op';
|
|
3
5
|
import * as React from 'react';
|
|
4
|
-
import { REACT_MOUNT_OP, REACT_UPDATE_OP, REACT_RENDER_OP } from './constants.js';
|
|
5
6
|
import { hoistNonReactStatics } from './hoist-non-react-statics.js';
|
|
6
7
|
|
|
7
8
|
const UNKNOWN_COMPONENT = "unknown";
|
|
@@ -15,8 +16,9 @@ class Profiler extends React.Component {
|
|
|
15
16
|
this._mountSpan = startInactiveSpan({
|
|
16
17
|
name: `<${name}>`,
|
|
17
18
|
onlyIfParent: true,
|
|
18
|
-
op: REACT_MOUNT_OP,
|
|
19
19
|
attributes: {
|
|
20
|
+
// TODO(conventions): Replace `'ui.mount'` with the `ui.mount` span op constant once it is released in `@sentry/conventions`.
|
|
21
|
+
[SENTRY_OP]: "ui.mount",
|
|
20
22
|
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.react.profiler",
|
|
21
23
|
"ui.component_name": name
|
|
22
24
|
}
|
|
@@ -37,9 +39,10 @@ class Profiler extends React.Component {
|
|
|
37
39
|
return startInactiveSpan({
|
|
38
40
|
name: `<${this.props.name}>`,
|
|
39
41
|
onlyIfParent: true,
|
|
40
|
-
op: REACT_UPDATE_OP,
|
|
41
42
|
startTime: now,
|
|
42
43
|
attributes: {
|
|
44
|
+
// TODO(conventions): Replace `'ui.update'` with the `ui.update` span op constant once it is released in `@sentry/conventions`.
|
|
45
|
+
[SENTRY_OP]: "ui.update",
|
|
43
46
|
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.react.profiler",
|
|
44
47
|
"ui.component_name": this.props.name,
|
|
45
48
|
"ui.react.changed_props": changedProps
|
|
@@ -67,9 +70,9 @@ class Profiler extends React.Component {
|
|
|
67
70
|
const renderSpan = startInactiveSpan({
|
|
68
71
|
onlyIfParent: true,
|
|
69
72
|
name: `<${name}>`,
|
|
70
|
-
op: REACT_RENDER_OP,
|
|
71
73
|
startTime,
|
|
72
74
|
attributes: {
|
|
75
|
+
[SENTRY_OP]: BROWSER_UI_RENDER_SPAN_OP,
|
|
73
76
|
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.react.profiler",
|
|
74
77
|
"ui.component_name": name
|
|
75
78
|
}
|
|
@@ -109,8 +112,9 @@ function useProfiler(name, options = {
|
|
|
109
112
|
return startInactiveSpan({
|
|
110
113
|
name: `<${name}>`,
|
|
111
114
|
onlyIfParent: true,
|
|
112
|
-
op: REACT_MOUNT_OP,
|
|
113
115
|
attributes: {
|
|
116
|
+
// TODO(conventions): Replace `'ui.mount'` with the `ui.mount` span op constant once it is released in `@sentry/conventions`.
|
|
117
|
+
[SENTRY_OP]: "ui.mount",
|
|
114
118
|
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.react.profiler",
|
|
115
119
|
"ui.component_name": name
|
|
116
120
|
}
|
|
@@ -127,9 +131,9 @@ function useProfiler(name, options = {
|
|
|
127
131
|
const renderSpan = startInactiveSpan({
|
|
128
132
|
name: `<${name}>`,
|
|
129
133
|
onlyIfParent: true,
|
|
130
|
-
op: REACT_RENDER_OP,
|
|
131
134
|
startTime,
|
|
132
135
|
attributes: {
|
|
136
|
+
[SENTRY_OP]: BROWSER_UI_RENDER_SPAN_OP,
|
|
133
137
|
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.react.profiler",
|
|
134
138
|
"ui.component_name": name
|
|
135
139
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profiler.js","sources":["../../src/profiler.tsx"],"sourcesContent":["import { startInactiveSpan } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, spanToJSON, timestampInSeconds, withActiveSpan } from '@sentry/core';\nimport * as React from 'react';\nimport { REACT_MOUNT_OP, REACT_RENDER_OP, REACT_UPDATE_OP } from './constants';\nimport { hoistNonReactStatics } from './hoist-non-react-statics';\n\nexport const UNKNOWN_COMPONENT = 'unknown';\n\nexport type ProfilerProps = {\n // The name of the component being profiled.\n name: string;\n // If the Profiler is disabled. False by default. This is useful if you want to disable profilers\n // in certain environments.\n disabled?: boolean;\n // If time component is on page should be displayed as spans. True by default.\n includeRender?: boolean;\n // If component updates should be displayed as spans. True by default.\n includeUpdates?: boolean;\n // Component that is being profiled.\n children?: React.ReactNode;\n // props given to component being profiled.\n updateProps: { [key: string]: unknown };\n};\n\n/**\n * The Profiler component leverages Sentry's Tracing integration to generate\n * spans based on component lifecycles.\n */\nclass Profiler extends React.Component<ProfilerProps> {\n /**\n * The span of the mount activity\n * Made protected for the React Native SDK to access\n */\n protected _mountSpan: Span | undefined;\n /**\n * The span that represents the duration of time between shouldComponentUpdate and componentDidUpdate\n */\n protected _updateSpan: Span | undefined;\n\n public constructor(props: ProfilerProps) {\n super(props);\n const { name, disabled = false } = this.props;\n\n if (disabled) {\n return;\n }\n\n this._mountSpan = startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n op: REACT_MOUNT_OP,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n }\n\n // If a component mounted, we can finish the mount activity.\n public componentDidMount(): void {\n if (this._mountSpan) {\n this._mountSpan.end();\n }\n }\n\n public shouldComponentUpdate({ updateProps, includeUpdates = true }: ProfilerProps): boolean {\n // Only generate an update span if includeUpdates is true, if there is a valid mountSpan,\n // and if the updateProps have changed. It is ok to not do a deep equality check here as it is expensive.\n // We are just trying to give baseline clues for further investigation.\n if (includeUpdates && this._mountSpan && updateProps !== this.props.updateProps) {\n // See what props have changed between the previous props, and the current props. This is\n // set as data on the span. We just store the prop keys as the values could be potentially very large.\n const changedProps = Object.keys(updateProps).filter(k => updateProps[k] !== this.props.updateProps[k]);\n if (changedProps.length > 0) {\n const now = timestampInSeconds();\n this._updateSpan = withActiveSpan(this._mountSpan, () => {\n return startInactiveSpan({\n name: `<${this.props.name}>`,\n onlyIfParent: true,\n op: REACT_UPDATE_OP,\n startTime: now,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': this.props.name,\n 'ui.react.changed_props': changedProps,\n },\n });\n });\n }\n }\n\n return true;\n }\n\n public componentDidUpdate(): void {\n if (this._updateSpan) {\n this._updateSpan.end();\n this._updateSpan = undefined;\n }\n }\n\n // If a component is unmounted, we can say it is no longer on the screen.\n // This means we can finish the span representing the component render.\n public componentWillUnmount(): void {\n const endTimestamp = timestampInSeconds();\n const { name, includeRender = true } = this.props;\n\n if (this._mountSpan && includeRender) {\n const startTime = spanToJSON(this._mountSpan).timestamp;\n withActiveSpan(this._mountSpan, () => {\n const renderSpan = startInactiveSpan({\n onlyIfParent: true,\n name: `<${name}>`,\n op: REACT_RENDER_OP,\n startTime,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n if (renderSpan) {\n // Have to cast to Span because the type of _mountSpan is Span | undefined\n // and not getting narrowed properly\n renderSpan.end(endTimestamp);\n }\n });\n }\n }\n\n public render(): React.ReactNode {\n return this.props.children;\n }\n}\n\n// React.Component default props are defined as static property on the class\nObject.assign(Profiler, {\n defaultProps: {\n disabled: false,\n includeRender: true,\n includeUpdates: true,\n },\n});\n\n/**\n * withProfiler is a higher order component that wraps a\n * component in a {@link Profiler} component. It is recommended that\n * the higher order component be used over the regular {@link Profiler} component.\n *\n * @param WrappedComponent component that is wrapped by Profiler\n * @param options the {@link ProfilerProps} you can pass into the Profiler\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction withProfiler<P extends Record<string, any>>(\n WrappedComponent: React.ComponentType<P>,\n // We do not want to have `updateProps` given in options, it is instead filled through the HOC.\n options?: Pick<Partial<ProfilerProps>, Exclude<keyof ProfilerProps, 'updateProps' | 'children'>>,\n): React.FC<P> {\n const componentDisplayName =\n options?.name || WrappedComponent.displayName || WrappedComponent.name || UNKNOWN_COMPONENT;\n\n const Wrapped: React.FC<P> = (props: P) => (\n <Profiler {...options} name={componentDisplayName} updateProps={props}>\n <WrappedComponent {...props} />\n </Profiler>\n );\n\n Wrapped.displayName = `profiler(${componentDisplayName})`;\n\n // Copy over static methods from Wrapped component to Profiler HOC\n // See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over\n hoistNonReactStatics(Wrapped, WrappedComponent);\n return Wrapped;\n}\n\n/**\n *\n * `useProfiler` is a React hook that profiles a React component.\n *\n * Requires React 16.8 or above.\n * @param name displayName of component being profiled\n */\nfunction useProfiler(\n name: string,\n options: { disabled?: boolean; hasRenderSpan?: boolean } = {\n disabled: false,\n hasRenderSpan: true,\n },\n): void {\n const [mountSpan] = React.useState(() => {\n if (options?.disabled) {\n return undefined;\n }\n\n return startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n op: REACT_MOUNT_OP,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n });\n\n React.useEffect(() => {\n if (mountSpan) {\n mountSpan.end();\n }\n\n return (): void => {\n if (mountSpan && options.hasRenderSpan) {\n const startTime = spanToJSON(mountSpan).timestamp;\n const endTimestamp = timestampInSeconds();\n\n const renderSpan = startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n op: REACT_RENDER_OP,\n startTime,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n if (renderSpan) {\n // Have to cast to Span because the type of _mountSpan is Span | undefined\n // and not getting narrowed properly\n renderSpan.end(endTimestamp);\n }\n }\n };\n // We only want this to run once.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n}\n\nexport { Profiler, useProfiler, withProfiler };\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"profiler.js","sources":["../../src/profiler.tsx"],"sourcesContent":["import { startInactiveSpan } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, spanToJSON, timestampInSeconds, withActiveSpan } from '@sentry/core';\nimport { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { BROWSER_UI_RENDER_SPAN_OP } from '@sentry/conventions/op';\nimport * as React from 'react';\nimport { hoistNonReactStatics } from './hoist-non-react-statics';\n\nexport const UNKNOWN_COMPONENT = 'unknown';\n\nexport type ProfilerProps = {\n // The name of the component being profiled.\n name: string;\n // If the Profiler is disabled. False by default. This is useful if you want to disable profilers\n // in certain environments.\n disabled?: boolean;\n // If time component is on page should be displayed as spans. True by default.\n includeRender?: boolean;\n // If component updates should be displayed as spans. True by default.\n includeUpdates?: boolean;\n // Component that is being profiled.\n children?: React.ReactNode;\n // props given to component being profiled.\n updateProps: { [key: string]: unknown };\n};\n\n/**\n * The Profiler component leverages Sentry's Tracing integration to generate\n * spans based on component lifecycles.\n */\nclass Profiler extends React.Component<ProfilerProps> {\n /**\n * The span of the mount activity\n * Made protected for the React Native SDK to access\n */\n protected _mountSpan: Span | undefined;\n /**\n * The span that represents the duration of time between shouldComponentUpdate and componentDidUpdate\n */\n protected _updateSpan: Span | undefined;\n\n public constructor(props: ProfilerProps) {\n super(props);\n const { name, disabled = false } = this.props;\n\n if (disabled) {\n return;\n }\n\n this._mountSpan = startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n attributes: {\n // TODO(conventions): Replace `'ui.mount'` with the `ui.mount` span op constant once it is released in `@sentry/conventions`.\n [SENTRY_OP]: 'ui.mount',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n }\n\n // If a component mounted, we can finish the mount activity.\n public componentDidMount(): void {\n if (this._mountSpan) {\n this._mountSpan.end();\n }\n }\n\n public shouldComponentUpdate({ updateProps, includeUpdates = true }: ProfilerProps): boolean {\n // Only generate an update span if includeUpdates is true, if there is a valid mountSpan,\n // and if the updateProps have changed. It is ok to not do a deep equality check here as it is expensive.\n // We are just trying to give baseline clues for further investigation.\n if (includeUpdates && this._mountSpan && updateProps !== this.props.updateProps) {\n // See what props have changed between the previous props, and the current props. This is\n // set as data on the span. We just store the prop keys as the values could be potentially very large.\n const changedProps = Object.keys(updateProps).filter(k => updateProps[k] !== this.props.updateProps[k]);\n if (changedProps.length > 0) {\n const now = timestampInSeconds();\n this._updateSpan = withActiveSpan(this._mountSpan, () => {\n return startInactiveSpan({\n name: `<${this.props.name}>`,\n onlyIfParent: true,\n startTime: now,\n attributes: {\n // TODO(conventions): Replace `'ui.update'` with the `ui.update` span op constant once it is released in `@sentry/conventions`.\n [SENTRY_OP]: 'ui.update',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': this.props.name,\n 'ui.react.changed_props': changedProps,\n },\n });\n });\n }\n }\n\n return true;\n }\n\n public componentDidUpdate(): void {\n if (this._updateSpan) {\n this._updateSpan.end();\n this._updateSpan = undefined;\n }\n }\n\n // If a component is unmounted, we can say it is no longer on the screen.\n // This means we can finish the span representing the component render.\n public componentWillUnmount(): void {\n const endTimestamp = timestampInSeconds();\n const { name, includeRender = true } = this.props;\n\n if (this._mountSpan && includeRender) {\n const startTime = spanToJSON(this._mountSpan).timestamp;\n withActiveSpan(this._mountSpan, () => {\n const renderSpan = startInactiveSpan({\n onlyIfParent: true,\n name: `<${name}>`,\n startTime,\n attributes: {\n [SENTRY_OP]: BROWSER_UI_RENDER_SPAN_OP,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n if (renderSpan) {\n // Have to cast to Span because the type of _mountSpan is Span | undefined\n // and not getting narrowed properly\n renderSpan.end(endTimestamp);\n }\n });\n }\n }\n\n public render(): React.ReactNode {\n return this.props.children;\n }\n}\n\n// React.Component default props are defined as static property on the class\nObject.assign(Profiler, {\n defaultProps: {\n disabled: false,\n includeRender: true,\n includeUpdates: true,\n },\n});\n\n/**\n * withProfiler is a higher order component that wraps a\n * component in a {@link Profiler} component. It is recommended that\n * the higher order component be used over the regular {@link Profiler} component.\n *\n * @param WrappedComponent component that is wrapped by Profiler\n * @param options the {@link ProfilerProps} you can pass into the Profiler\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction withProfiler<P extends Record<string, any>>(\n WrappedComponent: React.ComponentType<P>,\n // We do not want to have `updateProps` given in options, it is instead filled through the HOC.\n options?: Pick<Partial<ProfilerProps>, Exclude<keyof ProfilerProps, 'updateProps' | 'children'>>,\n): React.FC<P> {\n const componentDisplayName =\n options?.name || WrappedComponent.displayName || WrappedComponent.name || UNKNOWN_COMPONENT;\n\n const Wrapped: React.FC<P> = (props: P) => (\n <Profiler {...options} name={componentDisplayName} updateProps={props}>\n <WrappedComponent {...props} />\n </Profiler>\n );\n\n Wrapped.displayName = `profiler(${componentDisplayName})`;\n\n // Copy over static methods from Wrapped component to Profiler HOC\n // See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over\n hoistNonReactStatics(Wrapped, WrappedComponent);\n return Wrapped;\n}\n\n/**\n *\n * `useProfiler` is a React hook that profiles a React component.\n *\n * @param name displayName of component being profiled\n */\nfunction useProfiler(\n name: string,\n options: { disabled?: boolean; hasRenderSpan?: boolean } = {\n disabled: false,\n hasRenderSpan: true,\n },\n): void {\n const [mountSpan] = React.useState(() => {\n if (options?.disabled) {\n return undefined;\n }\n\n return startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n attributes: {\n // TODO(conventions): Replace `'ui.mount'` with the `ui.mount` span op constant once it is released in `@sentry/conventions`.\n [SENTRY_OP]: 'ui.mount',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n });\n\n React.useEffect(() => {\n if (mountSpan) {\n mountSpan.end();\n }\n\n return (): void => {\n if (mountSpan && options.hasRenderSpan) {\n const startTime = spanToJSON(mountSpan).timestamp;\n const endTimestamp = timestampInSeconds();\n\n const renderSpan = startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n startTime,\n attributes: {\n [SENTRY_OP]: BROWSER_UI_RENDER_SPAN_OP,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n if (renderSpan) {\n // Have to cast to Span because the type of _mountSpan is Span | undefined\n // and not getting narrowed properly\n renderSpan.end(endTimestamp);\n }\n }\n };\n // We only want this to run once.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n}\n\nexport { Profiler, useProfiler, withProfiler };\n"],"names":[],"mappings":";;;;;;;AAQO,MAAM,iBAAA,GAAoB;AAsBjC,MAAM,QAAA,SAAiB,MAAM,SAAA,CAAyB;AAAA,EAW7C,YAAY,KAAA,EAAsB;AACvC,IAAA,KAAA,CAAM,KAAK,CAAA;AACX,IAAA,MAAM,EAAE,IAAA,EAAM,QAAA,GAAW,KAAA,KAAU,IAAA,CAAK,KAAA;AAExC,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,aAAa,iBAAA,CAAkB;AAAA,MAClC,IAAA,EAAM,IAAI,IAAI,CAAA,CAAA,CAAA;AAAA,MACd,YAAA,EAAc,IAAA;AAAA,MACd,UAAA,EAAY;AAAA;AAAA,QAEV,CAAC,SAAS,GAAG,UAAA;AAAA,QACb,CAAC,gCAAgC,GAAG,wBAAA;AAAA,QACpC,mBAAA,EAAqB;AAAA;AACvB,KACD,CAAA;AAAA,EACH;AAAA;AAAA,EAGO,iBAAA,GAA0B;AAC/B,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,IAAA,CAAK,WAAW,GAAA,EAAI;AAAA,IACtB;AAAA,EACF;AAAA,EAEO,qBAAA,CAAsB,EAAE,WAAA,EAAa,cAAA,GAAiB,MAAK,EAA2B;AAI3F,IAAA,IAAI,kBAAkB,IAAA,CAAK,UAAA,IAAc,WAAA,KAAgB,IAAA,CAAK,MAAM,WAAA,EAAa;AAG/E,MAAA,MAAM,YAAA,GAAe,MAAA,CAAO,IAAA,CAAK,WAAW,EAAE,MAAA,CAAO,CAAA,CAAA,KAAK,WAAA,CAAY,CAAC,CAAA,KAAM,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,CAAC,CAAC,CAAA;AACtG,MAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,QAAA,MAAM,MAAM,kBAAA,EAAmB;AAC/B,QAAA,IAAA,CAAK,WAAA,GAAc,cAAA,CAAe,IAAA,CAAK,UAAA,EAAY,MAAM;AACvD,UAAA,OAAO,iBAAA,CAAkB;AAAA,YACvB,IAAA,EAAM,CAAA,CAAA,EAAI,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,CAAA,CAAA;AAAA,YACzB,YAAA,EAAc,IAAA;AAAA,YACd,SAAA,EAAW,GAAA;AAAA,YACX,UAAA,EAAY;AAAA;AAAA,cAEV,CAAC,SAAS,GAAG,WAAA;AAAA,cACb,CAAC,gCAAgC,GAAG,wBAAA;AAAA,cACpC,mBAAA,EAAqB,KAAK,KAAA,CAAM,IAAA;AAAA,cAChC,wBAAA,EAA0B;AAAA;AAC5B,WACD,CAAA;AAAA,QACH,CAAC,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEO,kBAAA,GAA2B;AAChC,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA,IAAA,CAAK,YAAY,GAAA,EAAI;AACrB,MAAA,IAAA,CAAK,WAAA,GAAc,MAAA;AAAA,IACrB;AAAA,EACF;AAAA;AAAA;AAAA,EAIO,oBAAA,GAA6B;AAClC,IAAA,MAAM,eAAe,kBAAA,EAAmB;AACxC,IAAA,MAAM,EAAE,IAAA,EAAM,aAAA,GAAgB,IAAA,KAAS,IAAA,CAAK,KAAA;AAE5C,IAAA,IAAI,IAAA,CAAK,cAAc,aAAA,EAAe;AACpC,MAAA,MAAM,SAAA,GAAY,UAAA,CAAW,IAAA,CAAK,UAAU,CAAA,CAAE,SAAA;AAC9C,MAAA,cAAA,CAAe,IAAA,CAAK,YAAY,MAAM;AACpC,QAAA,MAAM,aAAa,iBAAA,CAAkB;AAAA,UACnC,YAAA,EAAc,IAAA;AAAA,UACd,IAAA,EAAM,IAAI,IAAI,CAAA,CAAA,CAAA;AAAA,UACd,SAAA;AAAA,UACA,UAAA,EAAY;AAAA,YACV,CAAC,SAAS,GAAG,yBAAA;AAAA,YACb,CAAC,gCAAgC,GAAG,wBAAA;AAAA,YACpC,mBAAA,EAAqB;AAAA;AACvB,SACD,CAAA;AACD,QAAA,IAAI,UAAA,EAAY;AAGd,UAAA,UAAA,CAAW,IAAI,YAAY,CAAA;AAAA,QAC7B;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEO,MAAA,GAA0B;AAC/B,IAAA,OAAO,KAAK,KAAA,CAAM,QAAA;AAAA,EACpB;AACF;AAGA,MAAA,CAAO,OAAO,QAAA,EAAU;AAAA,EACtB,YAAA,EAAc;AAAA,IACZ,QAAA,EAAU,KAAA;AAAA,IACV,aAAA,EAAe,IAAA;AAAA,IACf,cAAA,EAAgB;AAAA;AAEpB,CAAC,CAAA;AAWD,SAAS,YAAA,CACP,kBAEA,OAAA,EACa;AACb,EAAA,MAAM,uBACJ,OAAA,EAAS,IAAA,IAAQ,gBAAA,CAAiB,WAAA,IAAe,iBAAiB,IAAA,IAAQ,iBAAA;AAE5E,EAAA,MAAM,OAAA,GAAuB,CAAC,KAAA,qBAC5B,KAAA,CAAA,aAAA,CAAC,YAAU,GAAG,OAAA,EAAS,IAAA,EAAM,oBAAA,EAAsB,aAAa,KAAA,EAAA,kBAC9D,KAAA,CAAA,aAAA,CAAC,gBAAA,EAAA,EAAkB,GAAG,OAAO,CAC/B,CAAA;AAGF,EAAA,OAAA,CAAQ,WAAA,GAAc,YAAY,oBAAoB,CAAA,CAAA,CAAA;AAItD,EAAA,oBAAA,CAAqB,SAAS,gBAAgB,CAAA;AAC9C,EAAA,OAAO,OAAA;AACT;AAQA,SAAS,WAAA,CACP,MACA,OAAA,GAA2D;AAAA,EACzD,QAAA,EAAU,KAAA;AAAA,EACV,aAAA,EAAe;AACjB,CAAA,EACM;AACN,EAAA,MAAM,CAAC,SAAS,CAAA,GAAI,KAAA,CAAM,SAAS,MAAM;AACvC,IAAA,IAAI,SAAS,QAAA,EAAU;AACrB,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,OAAO,iBAAA,CAAkB;AAAA,MACvB,IAAA,EAAM,IAAI,IAAI,CAAA,CAAA,CAAA;AAAA,MACd,YAAA,EAAc,IAAA;AAAA,MACd,UAAA,EAAY;AAAA;AAAA,QAEV,CAAC,SAAS,GAAG,UAAA;AAAA,QACb,CAAC,gCAAgC,GAAG,wBAAA;AAAA,QACpC,mBAAA,EAAqB;AAAA;AACvB,KACD,CAAA;AAAA,EACH,CAAC,CAAA;AAED,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,SAAA,CAAU,GAAA,EAAI;AAAA,IAChB;AAEA,IAAA,OAAO,MAAY;AACjB,MAAA,IAAI,SAAA,IAAa,QAAQ,aAAA,EAAe;AACtC,QAAA,MAAM,SAAA,GAAY,UAAA,CAAW,SAAS,CAAA,CAAE,SAAA;AACxC,QAAA,MAAM,eAAe,kBAAA,EAAmB;AAExC,QAAA,MAAM,aAAa,iBAAA,CAAkB;AAAA,UACnC,IAAA,EAAM,IAAI,IAAI,CAAA,CAAA,CAAA;AAAA,UACd,YAAA,EAAc,IAAA;AAAA,UACd,SAAA;AAAA,UACA,UAAA,EAAY;AAAA,YACV,CAAC,SAAS,GAAG,yBAAA;AAAA,YACb,CAAC,gCAAgC,GAAG,wBAAA;AAAA,YACpC,mBAAA,EAAqB;AAAA;AACvB,SACD,CAAA;AACD,QAAA,IAAI,UAAA,EAAY;AAGd,UAAA,UAAA,CAAW,IAAI,YAAY,CAAA;AAAA,QAC7B;AAAA,MACF;AAAA,IACF,CAAA;AAAA,EAGF,CAAA,EAAG,EAAE,CAAA;AACP;;;;"}
|
|
@@ -170,11 +170,7 @@ function updateNavigationSpan(activeRootSpan, location, allRoutes2, forceUpdate
|
|
|
170
170
|
activeRootSpan.setAttribute(URL_TEMPLATE, name);
|
|
171
171
|
}
|
|
172
172
|
if (!transactionNameHasWildcard(name) && source === "route") {
|
|
173
|
-
addNonEnumerableProperty(
|
|
174
|
-
activeRootSpan,
|
|
175
|
-
"__sentry_navigation_name_set__",
|
|
176
|
-
true
|
|
177
|
-
);
|
|
173
|
+
addNonEnumerableProperty(activeRootSpan, "__sentry_navigation_name_set__", true);
|
|
178
174
|
}
|
|
179
175
|
}
|
|
180
176
|
}
|
|
@@ -252,11 +248,7 @@ function createV6CompatibleWrapCreateBrowserRouter(createRouterFunction, version
|
|
|
252
248
|
const activeRootSpan = getActiveRootSpan();
|
|
253
249
|
const hasPatchRoutesOnNavigation = opts && "patchRoutesOnNavigation" in opts && typeof opts.patchRoutesOnNavigation === "function";
|
|
254
250
|
if (hasPatchRoutesOnNavigation && activeRootSpan) {
|
|
255
|
-
addNonEnumerableProperty(
|
|
256
|
-
activeRootSpan,
|
|
257
|
-
"__sentry_may_have_lazy_routes__",
|
|
258
|
-
true
|
|
259
|
-
);
|
|
251
|
+
addNonEnumerableProperty(activeRootSpan, "__sentry_may_have_lazy_routes__", true);
|
|
260
252
|
createDeferredLazyRoutePromise(activeRootSpan);
|
|
261
253
|
}
|
|
262
254
|
const wrappedOpts = wrapPatchRoutesOnNavigation(opts, false, activeRootSpan);
|
|
@@ -293,11 +285,7 @@ function createV6CompatibleWrapCreateMemoryRouter(createRouterFunction, version)
|
|
|
293
285
|
const memoryActiveRootSpanEarly = getActiveRootSpan();
|
|
294
286
|
const hasPatchRoutesOnNavigation = opts && "patchRoutesOnNavigation" in opts && typeof opts.patchRoutesOnNavigation === "function";
|
|
295
287
|
if (hasPatchRoutesOnNavigation && memoryActiveRootSpanEarly) {
|
|
296
|
-
addNonEnumerableProperty(
|
|
297
|
-
memoryActiveRootSpanEarly,
|
|
298
|
-
"__sentry_may_have_lazy_routes__",
|
|
299
|
-
true
|
|
300
|
-
);
|
|
288
|
+
addNonEnumerableProperty(memoryActiveRootSpanEarly, "__sentry_may_have_lazy_routes__", true);
|
|
301
289
|
createDeferredLazyRoutePromise(memoryActiveRootSpanEarly);
|
|
302
290
|
}
|
|
303
291
|
const wrappedOpts = wrapPatchRoutesOnNavigation(opts, true, memoryActiveRootSpanEarly);
|
|
@@ -410,10 +398,13 @@ function createV6CompatibleWrapUseRoutes(origUseRoutes, version) {
|
|
|
410
398
|
const location = _useLocation();
|
|
411
399
|
const navigationType = _useNavigationType();
|
|
412
400
|
const stableLocationParam = typeof locationArg === "string" || locationArg?.pathname ? locationArg : location;
|
|
401
|
+
useIsomorphicLayoutEffect(() => {
|
|
402
|
+
const added = addRoutesToAllRoutes(routes);
|
|
403
|
+
return () => removeRoutesFromAllRoutes(added);
|
|
404
|
+
});
|
|
413
405
|
useIsomorphicLayoutEffect(() => {
|
|
414
406
|
const normalizedLocation = typeof stableLocationParam === "string" ? { pathname: stableLocationParam } : stableLocationParam;
|
|
415
407
|
if (isMountRenderPass.current) {
|
|
416
|
-
addRoutesToAllRoutes(routes);
|
|
417
408
|
updatePageloadTransaction({
|
|
418
409
|
activeRootSpan: getActiveRootSpan(),
|
|
419
410
|
location: normalizedLocation,
|
|
@@ -556,11 +547,7 @@ function handleNavigation(opts) {
|
|
|
556
547
|
if (source === "route") {
|
|
557
548
|
trackedNav.span.setAttribute(URL_TEMPLATE, name);
|
|
558
549
|
}
|
|
559
|
-
addNonEnumerableProperty(
|
|
560
|
-
trackedNav.span,
|
|
561
|
-
"__sentry_navigation_name_set__",
|
|
562
|
-
true
|
|
563
|
-
);
|
|
550
|
+
addNonEnumerableProperty(trackedNav.span, "__sentry_navigation_name_set__", true);
|
|
564
551
|
trackedNav.routeName = name;
|
|
565
552
|
DEBUG_BUILD && debug.log(`[Tracing] Updated navigation span name from "${oldName}" to "${name}"`);
|
|
566
553
|
}
|
|
@@ -610,12 +597,20 @@ function handleNavigation(opts) {
|
|
|
610
597
|
}
|
|
611
598
|
}
|
|
612
599
|
function addRoutesToAllRoutes(routes) {
|
|
600
|
+
const added = [];
|
|
613
601
|
routes.forEach((route) => {
|
|
614
602
|
const extractedChildRoutes = getChildRoutesRecursively(route);
|
|
615
603
|
extractedChildRoutes.forEach((r) => {
|
|
616
604
|
allRoutes.add(r);
|
|
605
|
+
added.push(r);
|
|
617
606
|
});
|
|
618
607
|
});
|
|
608
|
+
return added;
|
|
609
|
+
}
|
|
610
|
+
function removeRoutesFromAllRoutes(routes) {
|
|
611
|
+
routes.forEach((route) => {
|
|
612
|
+
allRoutes.delete(route);
|
|
613
|
+
});
|
|
619
614
|
}
|
|
620
615
|
function getChildRoutesRecursively(route, allRoutes2 = /* @__PURE__ */ new Set()) {
|
|
621
616
|
if (!allRoutes2.has(route)) {
|
|
@@ -734,7 +729,7 @@ function patchSpanEnd(span, location, routes, basename, spanType) {
|
|
|
734
729
|
const client = getClient();
|
|
735
730
|
if (client && spanType === "navigation") {
|
|
736
731
|
const trackedNav = activeNavigationSpans.get(client);
|
|
737
|
-
if (trackedNav
|
|
732
|
+
if (trackedNav?.span === span) {
|
|
738
733
|
activeNavigationSpans.delete(client);
|
|
739
734
|
}
|
|
740
735
|
}
|
|
@@ -796,11 +791,14 @@ function createV6CompatibleWithSentryReactRouterRouting(Routes, version) {
|
|
|
796
791
|
const isMountRenderPass = React.useRef(true);
|
|
797
792
|
const location = _useLocation();
|
|
798
793
|
const navigationType = _useNavigationType();
|
|
794
|
+
const routes = _createRoutesFromChildren(props.children);
|
|
795
|
+
useIsomorphicLayoutEffect(() => {
|
|
796
|
+
const added = addRoutesToAllRoutes(routes);
|
|
797
|
+
return () => removeRoutesFromAllRoutes(added);
|
|
798
|
+
});
|
|
799
799
|
useIsomorphicLayoutEffect(
|
|
800
800
|
() => {
|
|
801
|
-
const routes = _createRoutesFromChildren(props.children);
|
|
802
801
|
if (isMountRenderPass.current) {
|
|
803
|
-
addRoutesToAllRoutes(routes);
|
|
804
802
|
updatePageloadTransaction({
|
|
805
803
|
activeRootSpan: getActiveRootSpan(),
|
|
806
804
|
location,
|