@sentry/react 10.64.0 → 10.66.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/reactrouter-compat-utils/instrumentation.js +15 -1
- package/build/cjs/reactrouter-compat-utils/instrumentation.js.map +1 -1
- package/build/cjs/reactrouter-compat-utils/utils.js +31 -0
- package/build/cjs/reactrouter-compat-utils/utils.js.map +1 -1
- package/build/cjs/reactrouter.js +6 -3
- package/build/cjs/reactrouter.js.map +1 -1
- package/build/cjs/reactrouterv3.js +5 -2
- package/build/cjs/reactrouterv3.js.map +1 -1
- package/build/cjs/tanstackrouter.js +50 -31
- package/build/cjs/tanstackrouter.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/reactrouter-compat-utils/instrumentation.js +15 -1
- package/build/esm/reactrouter-compat-utils/instrumentation.js.map +1 -1
- package/build/esm/reactrouter-compat-utils/utils.js +31 -0
- package/build/esm/reactrouter-compat-utils/utils.js.map +1 -1
- package/build/esm/reactrouter.js +6 -3
- package/build/esm/reactrouter.js.map +1 -1
- package/build/esm/reactrouterv3.js +5 -2
- package/build/esm/reactrouterv3.js.map +1 -1
- package/build/esm/tanstackrouter.js +51 -32
- package/build/esm/tanstackrouter.js.map +1 -1
- package/build/types/reactrouter-compat-utils/instrumentation.d.ts.map +1 -1
- package/build/types/reactrouter-compat-utils/utils.d.ts.map +1 -1
- package/build/types/reactrouter.d.ts.map +1 -1
- package/build/types/reactrouterv3.d.ts.map +1 -1
- package/build/types/tanstackrouter.d.ts.map +1 -1
- package/build/types/vendor/tanstackrouter-types.d.ts +1 -0
- package/build/types/vendor/tanstackrouter-types.d.ts.map +1 -1
- package/build/types-ts3.8/vendor/tanstackrouter-types.d.ts +1 -0
- package/package.json +4 -3
package/build/cjs/reactrouter.js
CHANGED
|
@@ -4,6 +4,7 @@ const browser = require('@sentry/browser');
|
|
|
4
4
|
const core = require('@sentry/core');
|
|
5
5
|
const React = require('react');
|
|
6
6
|
const hoistNonReactStatics = require('./hoist-non-react-statics.js');
|
|
7
|
+
const attributes = require('@sentry/conventions/attributes');
|
|
7
8
|
|
|
8
9
|
function reactRouterV4BrowserTracingIntegration(options) {
|
|
9
10
|
const integration = browser.browserTracingIntegration({
|
|
@@ -82,7 +83,8 @@ function instrumentReactRouter(client, instrumentPageLoad, instrumentNavigation,
|
|
|
82
83
|
attributes: {
|
|
83
84
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "pageload",
|
|
84
85
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.pageload.react.${instrumentationName}`,
|
|
85
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source
|
|
86
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
|
|
87
|
+
...source === "route" && { [attributes.URL_TEMPLATE]: name }
|
|
86
88
|
}
|
|
87
89
|
});
|
|
88
90
|
}
|
|
@@ -96,7 +98,8 @@ function instrumentReactRouter(client, instrumentPageLoad, instrumentNavigation,
|
|
|
96
98
|
attributes: {
|
|
97
99
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
|
|
98
100
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.navigation.react.${instrumentationName}`,
|
|
99
|
-
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source
|
|
101
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
|
|
102
|
+
...source === "route" && { [attributes.URL_TEMPLATE]: name }
|
|
100
103
|
}
|
|
101
104
|
});
|
|
102
105
|
}
|
|
@@ -131,7 +134,7 @@ function withSentryRouting(Route) {
|
|
|
131
134
|
core.getCurrentScope().setTransactionName(route);
|
|
132
135
|
if (activeRootSpan) {
|
|
133
136
|
activeRootSpan.updateName(route);
|
|
134
|
-
activeRootSpan.
|
|
137
|
+
activeRootSpan.setAttributes({ [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route", [attributes.URL_TEMPLATE]: route });
|
|
135
138
|
}
|
|
136
139
|
}
|
|
137
140
|
return /* @__PURE__ */ React.createElement(Route, { ...props });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactrouter.js","sources":["../../src/reactrouter.tsx"],"sourcesContent":["import {\n browserTracingIntegration,\n startBrowserTracingNavigationSpan,\n startBrowserTracingPageLoadSpan,\n WINDOW,\n} from '@sentry/browser';\nimport type { Client, Integration, Span, TransactionSource } from '@sentry/core';\nimport {\n getActiveSpan,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n spanToJSON,\n} from '@sentry/core';\nimport type { ReactElement } from 'react';\nimport * as React from 'react';\nimport { hoistNonReactStatics } from './hoist-non-react-statics';\nimport type { Action, Location } from './types';\n\n// We need to disable eslint no-explicit-any because any is required for the\n// react-router typings.\ntype Match = { path: string; url: string; params: Record<string, any>; isExact: boolean }; // eslint-disable-line @typescript-eslint/no-explicit-any\n\nexport type RouterHistory = {\n location?: Location;\n listen?(cb: (location: Location, action: Action) => void): void;\n} & Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n\nexport type RouteConfig = {\n [propName: string]: unknown;\n path?: string | string[];\n exact?: boolean;\n component?: ReactElement;\n routes?: RouteConfig[];\n};\n\nexport type MatchPath = (pathname: string, props: string | string[] | any, parent?: Match | null) => Match | null; // eslint-disable-line @typescript-eslint/no-explicit-any\n\ninterface ReactRouterOptions {\n history: RouterHistory;\n routes?: RouteConfig[];\n matchPath?: MatchPath;\n}\n\n/**\n * A browser tracing integration that uses React Router v4 to instrument navigations.\n * Expects `history` (and optionally `routes` and `matchPath`) to be passed as options.\n */\nexport function reactRouterV4BrowserTracingIntegration(\n options: Parameters<typeof browserTracingIntegration>[0] & ReactRouterOptions,\n): Integration {\n const integration = browserTracingIntegration({\n ...options,\n instrumentPageLoad: false,\n instrumentNavigation: false,\n });\n\n const { history, routes, matchPath, instrumentPageLoad = true, instrumentNavigation = true } = options;\n\n return {\n ...integration,\n afterAllSetup(client) {\n integration.afterAllSetup(client);\n\n instrumentReactRouter(\n client,\n instrumentPageLoad,\n instrumentNavigation,\n history,\n 'reactrouter_v4',\n routes,\n matchPath,\n );\n },\n };\n}\n\n/**\n * A browser tracing integration that uses React Router v5 to instrument navigations.\n * Expects `history` (and optionally `routes` and `matchPath`) to be passed as options.\n */\nexport function reactRouterV5BrowserTracingIntegration(\n options: Parameters<typeof browserTracingIntegration>[0] & ReactRouterOptions,\n): Integration {\n const integration = browserTracingIntegration({\n ...options,\n instrumentPageLoad: false,\n instrumentNavigation: false,\n });\n\n const { history, routes, matchPath, instrumentPageLoad = true, instrumentNavigation = true } = options;\n\n return {\n ...integration,\n afterAllSetup(client) {\n integration.afterAllSetup(client);\n\n instrumentReactRouter(\n client,\n instrumentPageLoad,\n instrumentNavigation,\n history,\n 'reactrouter_v5',\n routes,\n matchPath,\n );\n },\n };\n}\n\nfunction instrumentReactRouter(\n client: Client,\n instrumentPageLoad: boolean,\n instrumentNavigation: boolean,\n history: RouterHistory,\n instrumentationName: string,\n allRoutes: RouteConfig[] = [],\n matchPath?: MatchPath,\n): void {\n function getInitPathName(): string | undefined {\n if (history.location) {\n return history.location.pathname;\n }\n\n if (WINDOW.location) {\n return WINDOW.location.pathname;\n }\n\n return undefined;\n }\n\n /**\n * Normalizes a transaction name. Returns the new name as well as the\n * source of the transaction.\n *\n * @param pathname The initial pathname we normalize\n */\n function normalizeTransactionName(pathname: string): [string, TransactionSource] {\n if (allRoutes.length === 0 || !matchPath) {\n return [pathname, 'url'];\n }\n\n const branches = matchRoutes(allRoutes, pathname, matchPath);\n for (const branch of branches) {\n if (branch.match.isExact) {\n return [branch.match.path, 'route'];\n }\n }\n\n return [pathname, 'url'];\n }\n\n if (instrumentPageLoad) {\n const initPathName = getInitPathName();\n if (initPathName) {\n const [name, source] = normalizeTransactionName(initPathName);\n startBrowserTracingPageLoadSpan(client, {\n name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.pageload.react.${instrumentationName}`,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,\n },\n });\n }\n }\n\n if (instrumentNavigation && history.listen) {\n history.listen((location, action) => {\n if (action && (action === 'PUSH' || action === 'POP')) {\n const [name, source] = normalizeTransactionName(location.pathname);\n startBrowserTracingNavigationSpan(client, {\n name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.navigation.react.${instrumentationName}`,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,\n },\n });\n }\n });\n }\n}\n\n/**\n * Matches a set of routes to a pathname\n * Based on implementation from\n */\nfunction matchRoutes(\n routes: RouteConfig[],\n pathname: string,\n matchPath: MatchPath,\n branch: Array<{ route: RouteConfig; match: Match }> = [],\n): Array<{ route: RouteConfig; match: Match }> {\n routes.some(route => {\n const match = route.path\n ? matchPath(pathname, route)\n : branch.length\n ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n branch[branch.length - 1]!.match // use parent match\n : computeRootMatch(pathname); // use default \"root\" match\n\n if (match) {\n branch.push({ route, match });\n\n if (route.routes) {\n matchRoutes(route.routes, pathname, matchPath, branch);\n }\n }\n\n return !!match;\n });\n\n return branch;\n}\n\nfunction computeRootMatch(pathname: string): Match {\n return { path: '/', url: '/', params: {}, isExact: pathname === '/' };\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */\nexport function withSentryRouting<P extends Record<string, any>, R extends React.ComponentType<P>>(Route: R): R {\n const componentDisplayName = Route.displayName || Route.name;\n\n const WrappedRoute: React.FC<P> = (props: P) => {\n if (props?.computedMatch?.isExact) {\n const route = props.computedMatch.path;\n const activeRootSpan = getActiveRootSpan();\n\n getCurrentScope().setTransactionName(route);\n\n if (activeRootSpan) {\n activeRootSpan.updateName(route);\n activeRootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'route');\n }\n }\n\n // @ts-expect-error Setting more specific React Component typing for `R` generic above\n // will break advanced type inference done by react router params:\n // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13dc4235c069e25fe7ee16e11f529d909f9f3ff8/types/react-router/index.d.ts#L154-L164\n return <Route {...props} />;\n };\n\n WrappedRoute.displayName = `sentryRoute(${componentDisplayName})`;\n hoistNonReactStatics(WrappedRoute, Route);\n // @ts-expect-error Setting more specific React Component typing for `R` generic above\n // will break advanced type inference done by react router params:\n // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13dc4235c069e25fe7ee16e11f529d909f9f3ff8/types/react-router/index.d.ts#L154-L164\n return WrappedRoute;\n}\n/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */\n\nfunction getActiveRootSpan(): Span | undefined {\n const span = getActiveSpan();\n const rootSpan = span && getRootSpan(span);\n\n if (!rootSpan) {\n return undefined;\n }\n\n const op = spanToJSON(rootSpan).op;\n\n // Only use this root span if it is a pageload or navigation span\n return op === 'navigation' || op === 'pageload' ? rootSpan : undefined;\n}\n"],"names":["browserTracingIntegration","WINDOW","startBrowserTracingPageLoadSpan","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","startBrowserTracingNavigationSpan","getCurrentScope","hoistNonReactStatics","getActiveSpan","getRootSpan","spanToJSON"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reactrouter.js","sources":["../../src/reactrouter.tsx"],"sourcesContent":["import {\n browserTracingIntegration,\n startBrowserTracingNavigationSpan,\n startBrowserTracingPageLoadSpan,\n WINDOW,\n} from '@sentry/browser';\nimport type { Client, Integration, Span, TransactionSource } from '@sentry/core';\nimport {\n getActiveSpan,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n spanToJSON,\n} from '@sentry/core';\nimport type { ReactElement } from 'react';\nimport * as React from 'react';\nimport { hoistNonReactStatics } from './hoist-non-react-statics';\nimport type { Action, Location } from './types';\nimport { URL_TEMPLATE } from '@sentry/conventions/attributes';\n\n// We need to disable eslint no-explicit-any because any is required for the\n// react-router typings.\ntype Match = { path: string; url: string; params: Record<string, any>; isExact: boolean }; // eslint-disable-line @typescript-eslint/no-explicit-any\n\nexport type RouterHistory = {\n location?: Location;\n listen?(cb: (location: Location, action: Action) => void): void;\n} & Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n\nexport type RouteConfig = {\n [propName: string]: unknown;\n path?: string | string[];\n exact?: boolean;\n component?: ReactElement;\n routes?: RouteConfig[];\n};\n\nexport type MatchPath = (pathname: string, props: string | string[] | any, parent?: Match | null) => Match | null; // eslint-disable-line @typescript-eslint/no-explicit-any\n\ninterface ReactRouterOptions {\n history: RouterHistory;\n routes?: RouteConfig[];\n matchPath?: MatchPath;\n}\n\n/**\n * A browser tracing integration that uses React Router v4 to instrument navigations.\n * Expects `history` (and optionally `routes` and `matchPath`) to be passed as options.\n */\nexport function reactRouterV4BrowserTracingIntegration(\n options: Parameters<typeof browserTracingIntegration>[0] & ReactRouterOptions,\n): Integration {\n const integration = browserTracingIntegration({\n ...options,\n instrumentPageLoad: false,\n instrumentNavigation: false,\n });\n\n const { history, routes, matchPath, instrumentPageLoad = true, instrumentNavigation = true } = options;\n\n return {\n ...integration,\n afterAllSetup(client) {\n integration.afterAllSetup(client);\n\n instrumentReactRouter(\n client,\n instrumentPageLoad,\n instrumentNavigation,\n history,\n 'reactrouter_v4',\n routes,\n matchPath,\n );\n },\n };\n}\n\n/**\n * A browser tracing integration that uses React Router v5 to instrument navigations.\n * Expects `history` (and optionally `routes` and `matchPath`) to be passed as options.\n */\nexport function reactRouterV5BrowserTracingIntegration(\n options: Parameters<typeof browserTracingIntegration>[0] & ReactRouterOptions,\n): Integration {\n const integration = browserTracingIntegration({\n ...options,\n instrumentPageLoad: false,\n instrumentNavigation: false,\n });\n\n const { history, routes, matchPath, instrumentPageLoad = true, instrumentNavigation = true } = options;\n\n return {\n ...integration,\n afterAllSetup(client) {\n integration.afterAllSetup(client);\n\n instrumentReactRouter(\n client,\n instrumentPageLoad,\n instrumentNavigation,\n history,\n 'reactrouter_v5',\n routes,\n matchPath,\n );\n },\n };\n}\n\nfunction instrumentReactRouter(\n client: Client,\n instrumentPageLoad: boolean,\n instrumentNavigation: boolean,\n history: RouterHistory,\n instrumentationName: string,\n allRoutes: RouteConfig[] = [],\n matchPath?: MatchPath,\n): void {\n function getInitPathName(): string | undefined {\n if (history.location) {\n return history.location.pathname;\n }\n\n if (WINDOW.location) {\n return WINDOW.location.pathname;\n }\n\n return undefined;\n }\n\n /**\n * Normalizes a transaction name. Returns the new name as well as the\n * source of the transaction.\n *\n * @param pathname The initial pathname we normalize\n */\n function normalizeTransactionName(pathname: string): [string, TransactionSource] {\n if (allRoutes.length === 0 || !matchPath) {\n return [pathname, 'url'];\n }\n\n const branches = matchRoutes(allRoutes, pathname, matchPath);\n for (const branch of branches) {\n if (branch.match.isExact) {\n return [branch.match.path, 'route'];\n }\n }\n\n return [pathname, 'url'];\n }\n\n if (instrumentPageLoad) {\n const initPathName = getInitPathName();\n if (initPathName) {\n const [name, source] = normalizeTransactionName(initPathName);\n startBrowserTracingPageLoadSpan(client, {\n name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.pageload.react.${instrumentationName}`,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,\n ...(source === 'route' && { [URL_TEMPLATE]: name }),\n },\n });\n }\n }\n\n if (instrumentNavigation && history.listen) {\n history.listen((location, action) => {\n if (action && (action === 'PUSH' || action === 'POP')) {\n const [name, source] = normalizeTransactionName(location.pathname);\n startBrowserTracingNavigationSpan(client, {\n name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.navigation.react.${instrumentationName}`,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,\n ...(source === 'route' && { [URL_TEMPLATE]: name }),\n },\n });\n }\n });\n }\n}\n\n/**\n * Matches a set of routes to a pathname\n * Based on implementation from\n */\nfunction matchRoutes(\n routes: RouteConfig[],\n pathname: string,\n matchPath: MatchPath,\n branch: Array<{ route: RouteConfig; match: Match }> = [],\n): Array<{ route: RouteConfig; match: Match }> {\n routes.some(route => {\n const match = route.path\n ? matchPath(pathname, route)\n : branch.length\n ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n branch[branch.length - 1]!.match // use parent match\n : computeRootMatch(pathname); // use default \"root\" match\n\n if (match) {\n branch.push({ route, match });\n\n if (route.routes) {\n matchRoutes(route.routes, pathname, matchPath, branch);\n }\n }\n\n return !!match;\n });\n\n return branch;\n}\n\nfunction computeRootMatch(pathname: string): Match {\n return { path: '/', url: '/', params: {}, isExact: pathname === '/' };\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */\nexport function withSentryRouting<P extends Record<string, any>, R extends React.ComponentType<P>>(Route: R): R {\n const componentDisplayName = Route.displayName || Route.name;\n\n const WrappedRoute: React.FC<P> = (props: P) => {\n if (props?.computedMatch?.isExact) {\n const route = props.computedMatch.path;\n const activeRootSpan = getActiveRootSpan();\n\n getCurrentScope().setTransactionName(route);\n\n if (activeRootSpan) {\n activeRootSpan.updateName(route);\n activeRootSpan.setAttributes({ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route', [URL_TEMPLATE]: route });\n }\n }\n\n // @ts-expect-error Setting more specific React Component typing for `R` generic above\n // will break advanced type inference done by react router params:\n // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13dc4235c069e25fe7ee16e11f529d909f9f3ff8/types/react-router/index.d.ts#L154-L164\n return <Route {...props} />;\n };\n\n WrappedRoute.displayName = `sentryRoute(${componentDisplayName})`;\n hoistNonReactStatics(WrappedRoute, Route);\n // @ts-expect-error Setting more specific React Component typing for `R` generic above\n // will break advanced type inference done by react router params:\n // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/13dc4235c069e25fe7ee16e11f529d909f9f3ff8/types/react-router/index.d.ts#L154-L164\n return WrappedRoute;\n}\n/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */\n\nfunction getActiveRootSpan(): Span | undefined {\n const span = getActiveSpan();\n const rootSpan = span && getRootSpan(span);\n\n if (!rootSpan) {\n return undefined;\n }\n\n const op = spanToJSON(rootSpan).op;\n\n // Only use this root span if it is a pageload or navigation span\n return op === 'navigation' || op === 'pageload' ? rootSpan : undefined;\n}\n"],"names":["browserTracingIntegration","WINDOW","startBrowserTracingPageLoadSpan","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","URL_TEMPLATE","startBrowserTracingNavigationSpan","getCurrentScope","hoistNonReactStatics","getActiveSpan","getRootSpan","spanToJSON"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
|
|
3
3
|
const browser = require('@sentry/browser');
|
|
4
4
|
const browser$1 = require('@sentry/core/browser');
|
|
5
|
+
const attributes = require('@sentry/conventions/attributes');
|
|
5
6
|
|
|
6
7
|
function reactRouterV3BrowserTracingIntegration(options) {
|
|
7
8
|
const integration = browser.browserTracingIntegration({
|
|
@@ -25,7 +26,8 @@ function reactRouterV3BrowserTracingIntegration(options) {
|
|
|
25
26
|
attributes: {
|
|
26
27
|
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "pageload",
|
|
27
28
|
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.pageload.react.reactrouter_v3",
|
|
28
|
-
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source
|
|
29
|
+
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
|
|
30
|
+
...source === "route" && { [attributes.URL_TEMPLATE]: localName }
|
|
29
31
|
}
|
|
30
32
|
});
|
|
31
33
|
}
|
|
@@ -44,7 +46,8 @@ function reactRouterV3BrowserTracingIntegration(options) {
|
|
|
44
46
|
attributes: {
|
|
45
47
|
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
|
|
46
48
|
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.navigation.react.reactrouter_v3",
|
|
47
|
-
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source
|
|
49
|
+
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
|
|
50
|
+
...source === "route" && { [attributes.URL_TEMPLATE]: localName }
|
|
48
51
|
}
|
|
49
52
|
});
|
|
50
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactrouterv3.js","sources":["../../src/reactrouterv3.ts"],"sourcesContent":["import {\n browserTracingIntegration,\n startBrowserTracingNavigationSpan,\n startBrowserTracingPageLoadSpan,\n WINDOW,\n} from '@sentry/browser';\nimport type { Integration, TransactionSource } 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 { Location } from './types';\n\n// Many of the types below had to be mocked out to prevent typescript issues\n// these types are required for correct functionality.\n\ntype HistoryV3 = {\n location?: Location;\n listen?(cb: (location: Location) => void): void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n} & Record<string, any>;\n\nexport type Route = { path?: string; childRoutes?: Route[] };\n\nexport type Match = (\n props: { location: Location; routes: Route[] },\n cb: (error?: Error, _redirectLocation?: Location, renderProps?: { routes?: Route[] }) => void,\n) => void;\n\ntype ReactRouterV3TransactionSource = Extract<TransactionSource, 'url' | 'route'>;\n\ninterface ReactRouterOptions {\n history: HistoryV3;\n routes: Route[];\n match: Match;\n}\n\n/**\n * A browser tracing integration that uses React Router v3 to instrument navigations.\n * Expects `history` (and optionally `routes` and `matchPath`) to be passed as options.\n */\nexport function reactRouterV3BrowserTracingIntegration(\n options: Parameters<typeof browserTracingIntegration>[0] & ReactRouterOptions,\n): Integration {\n const integration = browserTracingIntegration({\n ...options,\n instrumentPageLoad: false,\n instrumentNavigation: false,\n });\n\n const { history, routes, match, instrumentPageLoad = true, instrumentNavigation = true } = options;\n\n return {\n ...integration,\n afterAllSetup(client) {\n integration.afterAllSetup(client);\n\n if (instrumentPageLoad && WINDOW.location) {\n normalizeTransactionName(\n routes,\n WINDOW.location as unknown as Location,\n match,\n (localName: string, source: ReactRouterV3TransactionSource = 'url') => {\n startBrowserTracingPageLoadSpan(client, {\n name: localName,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.react.reactrouter_v3',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,\n },\n });\n },\n );\n }\n\n if (instrumentNavigation && history.listen) {\n history.listen(location => {\n if (location.action === 'PUSH' || location.action === 'POP') {\n normalizeTransactionName(\n routes,\n location,\n match,\n (localName: string, source: TransactionSource = 'url') => {\n startBrowserTracingNavigationSpan(client, {\n name: localName,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react.reactrouter_v3',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,\n },\n });\n },\n );\n }\n });\n }\n },\n };\n}\n\n/**\n * Normalize transaction names using `Router.match`\n */\nfunction normalizeTransactionName(\n appRoutes: Route[],\n location: Location,\n match: Match,\n callback: (pathname: string, source?: ReactRouterV3TransactionSource) => void,\n): void {\n let name = location.pathname;\n match(\n {\n location,\n routes: appRoutes,\n },\n (error, _redirectLocation, renderProps) => {\n if (error || !renderProps) {\n return callback(name);\n }\n\n const routePath = getRouteStringFromRoutes(renderProps.routes || []);\n if (routePath.length === 0 || routePath === '/*') {\n return callback(name);\n }\n\n name = routePath;\n return callback(name, 'route');\n },\n );\n}\n\n/**\n * Generate route name from array of routes\n */\nfunction getRouteStringFromRoutes(routes: Route[]): string {\n if (!Array.isArray(routes) || routes.length === 0) {\n return '';\n }\n\n const routesWithPaths: Route[] = routes.filter((route: Route) => !!route.path);\n\n let index = -1;\n for (let x = routesWithPaths.length - 1; x >= 0; x--) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const route = routesWithPaths[x]!;\n if (route.path?.startsWith('/')) {\n index = x;\n break;\n }\n }\n\n return routesWithPaths.slice(index).reduce((acc, { path }) => {\n const pathSegment = acc === '/' || acc === '' ? path : `/${path}`;\n return `${acc}${pathSegment}`;\n }, '');\n}\n"],"names":["browserTracingIntegration","WINDOW","startBrowserTracingPageLoadSpan","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","startBrowserTracingNavigationSpan"],"mappings":"
|
|
1
|
+
{"version":3,"file":"reactrouterv3.js","sources":["../../src/reactrouterv3.ts"],"sourcesContent":["import {\n browserTracingIntegration,\n startBrowserTracingNavigationSpan,\n startBrowserTracingPageLoadSpan,\n WINDOW,\n} from '@sentry/browser';\nimport type { Integration, TransactionSource } 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 { Location } from './types';\nimport { URL_TEMPLATE } from '@sentry/conventions/attributes';\n\n// Many of the types below had to be mocked out to prevent typescript issues\n// these types are required for correct functionality.\n\ntype HistoryV3 = {\n location?: Location;\n listen?(cb: (location: Location) => void): void;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n} & Record<string, any>;\n\nexport type Route = { path?: string; childRoutes?: Route[] };\n\nexport type Match = (\n props: { location: Location; routes: Route[] },\n cb: (error?: Error, _redirectLocation?: Location, renderProps?: { routes?: Route[] }) => void,\n) => void;\n\ntype ReactRouterV3TransactionSource = Extract<TransactionSource, 'url' | 'route'>;\n\ninterface ReactRouterOptions {\n history: HistoryV3;\n routes: Route[];\n match: Match;\n}\n\n/**\n * A browser tracing integration that uses React Router v3 to instrument navigations.\n * Expects `history` (and optionally `routes` and `matchPath`) to be passed as options.\n */\nexport function reactRouterV3BrowserTracingIntegration(\n options: Parameters<typeof browserTracingIntegration>[0] & ReactRouterOptions,\n): Integration {\n const integration = browserTracingIntegration({\n ...options,\n instrumentPageLoad: false,\n instrumentNavigation: false,\n });\n\n const { history, routes, match, instrumentPageLoad = true, instrumentNavigation = true } = options;\n\n return {\n ...integration,\n afterAllSetup(client) {\n integration.afterAllSetup(client);\n\n if (instrumentPageLoad && WINDOW.location) {\n normalizeTransactionName(\n routes,\n WINDOW.location as unknown as Location,\n match,\n (localName: string, source: ReactRouterV3TransactionSource = 'url') => {\n startBrowserTracingPageLoadSpan(client, {\n name: localName,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.react.reactrouter_v3',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,\n ...(source === 'route' && { [URL_TEMPLATE]: localName }),\n },\n });\n },\n );\n }\n\n if (instrumentNavigation && history.listen) {\n history.listen(location => {\n if (location.action === 'PUSH' || location.action === 'POP') {\n normalizeTransactionName(\n routes,\n location,\n match,\n (localName: string, source: TransactionSource = 'url') => {\n startBrowserTracingNavigationSpan(client, {\n name: localName,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react.reactrouter_v3',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,\n ...(source === 'route' && { [URL_TEMPLATE]: localName }),\n },\n });\n },\n );\n }\n });\n }\n },\n };\n}\n\n/**\n * Normalize transaction names using `Router.match`\n */\nfunction normalizeTransactionName(\n appRoutes: Route[],\n location: Location,\n match: Match,\n callback: (pathname: string, source?: ReactRouterV3TransactionSource) => void,\n): void {\n let name = location.pathname;\n match(\n {\n location,\n routes: appRoutes,\n },\n (error, _redirectLocation, renderProps) => {\n if (error || !renderProps) {\n return callback(name);\n }\n\n const routePath = getRouteStringFromRoutes(renderProps.routes || []);\n if (routePath.length === 0 || routePath === '/*') {\n return callback(name);\n }\n\n name = routePath;\n return callback(name, 'route');\n },\n );\n}\n\n/**\n * Generate route name from array of routes\n */\nfunction getRouteStringFromRoutes(routes: Route[]): string {\n if (!Array.isArray(routes) || routes.length === 0) {\n return '';\n }\n\n const routesWithPaths: Route[] = routes.filter((route: Route) => !!route.path);\n\n let index = -1;\n for (let x = routesWithPaths.length - 1; x >= 0; x--) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const route = routesWithPaths[x]!;\n if (route.path?.startsWith('/')) {\n index = x;\n break;\n }\n }\n\n return routesWithPaths.slice(index).reduce((acc, { path }) => {\n const pathSegment = acc === '/' || acc === '' ? path : `/${path}`;\n return `${acc}${pathSegment}`;\n }, '');\n}\n"],"names":["browserTracingIntegration","WINDOW","startBrowserTracingPageLoadSpan","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","URL_TEMPLATE","startBrowserTracingNavigationSpan"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
|
|
3
3
|
const browser = require('@sentry/browser');
|
|
4
4
|
const browser$1 = require('@sentry/core/browser');
|
|
5
|
+
const attributes = require('@sentry/conventions/attributes');
|
|
5
6
|
|
|
6
7
|
function tanstackRouterBrowserTracingIntegration(router, options = {}) {
|
|
7
8
|
const castRouterInstance = router;
|
|
@@ -23,6 +24,15 @@ function tanstackRouterBrowserTracingIntegration(router, options = {}) {
|
|
|
23
24
|
const lastMatch = matchedRoutes[matchedRoutes.length - 1];
|
|
24
25
|
return lastMatch?.routeId !== "__root__" ? lastMatch : void 0;
|
|
25
26
|
};
|
|
27
|
+
const applyRouteMatch = (span, match, toLocation, fallbackName) => {
|
|
28
|
+
span.updateName(match ? match.routeId : fallbackName);
|
|
29
|
+
span.setAttribute(browser$1.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, match ? "route" : "url");
|
|
30
|
+
span.setAttributes({
|
|
31
|
+
...match && { [attributes.URL_TEMPLATE]: match.routeId },
|
|
32
|
+
...locationToSpanUrlAttributes(castRouterInstance, toLocation),
|
|
33
|
+
...routeMatchToParamSpanAttributes(match)
|
|
34
|
+
});
|
|
35
|
+
};
|
|
26
36
|
const initialWindowLocation = browser.WINDOW.location;
|
|
27
37
|
if (instrumentPageLoad && initialWindowLocation) {
|
|
28
38
|
const routeMatch = resolveRouteMatch(
|
|
@@ -35,6 +45,7 @@ function tanstackRouterBrowserTracingIntegration(router, options = {}) {
|
|
|
35
45
|
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "pageload",
|
|
36
46
|
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.pageload.react.tanstack_router",
|
|
37
47
|
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: routeMatch ? "route" : "url",
|
|
48
|
+
...routeMatch && { [attributes.URL_TEMPLATE]: routeMatch.routeId },
|
|
38
49
|
...routeMatchToParamSpanAttributes(routeMatch)
|
|
39
50
|
}
|
|
40
51
|
});
|
|
@@ -43,43 +54,38 @@ function tanstackRouterBrowserTracingIntegration(router, options = {}) {
|
|
|
43
54
|
if (!pageloadSpan) {
|
|
44
55
|
return;
|
|
45
56
|
}
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
pageloadSpan.setAttribute(browser$1.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, "route");
|
|
50
|
-
pageloadSpan.setAttributes(routeMatchToParamSpanAttributes(resolvedMatch));
|
|
51
|
-
}
|
|
57
|
+
const { toLocation } = onResolvedArgs;
|
|
58
|
+
const resolvedMatch = resolveRouteMatch(toLocation.pathname, toLocation.search);
|
|
59
|
+
applyRouteMatch(pageloadSpan, resolvedMatch, toLocation, toLocation.pathname);
|
|
52
60
|
});
|
|
53
61
|
}
|
|
54
62
|
if (instrumentNavigation) {
|
|
55
63
|
let inFlightNavigationSpan;
|
|
56
|
-
const applyRouteMatch = (span, match, fallbackName) => {
|
|
57
|
-
span.updateName(match ? match.routeId : fallbackName);
|
|
58
|
-
span.setAttribute(browser$1.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, match ? "route" : "url");
|
|
59
|
-
span.setAttributes(routeMatchToParamSpanAttributes(match));
|
|
60
|
-
};
|
|
61
64
|
castRouterInstance.subscribe("onBeforeLoad", (onBeforeLoadArgs) => {
|
|
62
|
-
|
|
65
|
+
const { toLocation, fromLocation } = onBeforeLoadArgs;
|
|
66
|
+
if (!fromLocation || toLocation.state === fromLocation.state) {
|
|
63
67
|
return;
|
|
64
68
|
}
|
|
65
|
-
const routeMatch = resolveRouteMatch(
|
|
66
|
-
|
|
67
|
-
onBeforeLoadArgs.toLocation.search
|
|
68
|
-
);
|
|
69
|
-
const fallbackName = browser.WINDOW.location.pathname;
|
|
69
|
+
const routeMatch = resolveRouteMatch(toLocation.pathname, toLocation.search);
|
|
70
|
+
const fallbackName = browser.WINDOW.location?.pathname || toLocation.pathname;
|
|
70
71
|
if (inFlightNavigationSpan) {
|
|
71
|
-
applyRouteMatch(inFlightNavigationSpan, routeMatch, fallbackName);
|
|
72
|
+
applyRouteMatch(inFlightNavigationSpan, routeMatch, toLocation, fallbackName);
|
|
72
73
|
return;
|
|
73
74
|
}
|
|
74
|
-
inFlightNavigationSpan = browser.startBrowserTracingNavigationSpan(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
inFlightNavigationSpan = browser.startBrowserTracingNavigationSpan(
|
|
76
|
+
client,
|
|
77
|
+
{
|
|
78
|
+
name: routeMatch ? routeMatch.routeId : fallbackName,
|
|
79
|
+
attributes: {
|
|
80
|
+
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
|
|
81
|
+
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.navigation.react.tanstack_router",
|
|
82
|
+
[browser$1.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: routeMatch ? "route" : "url",
|
|
83
|
+
...routeMatch && { [attributes.URL_TEMPLATE]: routeMatch.routeId },
|
|
84
|
+
...routeMatchToParamSpanAttributes(routeMatch)
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
{ url: locationToAbsoluteUrl(castRouterInstance, toLocation) }
|
|
88
|
+
);
|
|
83
89
|
});
|
|
84
90
|
castRouterInstance.subscribe("onResolved", (onResolvedArgs) => {
|
|
85
91
|
const span = inFlightNavigationSpan;
|
|
@@ -87,15 +93,28 @@ function tanstackRouterBrowserTracingIntegration(router, options = {}) {
|
|
|
87
93
|
if (!span) {
|
|
88
94
|
return;
|
|
89
95
|
}
|
|
90
|
-
const
|
|
96
|
+
const { toLocation } = onResolvedArgs;
|
|
97
|
+
const resolvedMatch = resolveRouteMatch(toLocation.pathname, toLocation.search);
|
|
91
98
|
if (resolvedMatch) {
|
|
92
|
-
applyRouteMatch(span, resolvedMatch, browser.WINDOW.location.pathname);
|
|
99
|
+
applyRouteMatch(span, resolvedMatch, toLocation, browser.WINDOW.location?.pathname || toLocation.pathname);
|
|
93
100
|
}
|
|
94
101
|
});
|
|
95
102
|
}
|
|
96
103
|
}
|
|
97
104
|
};
|
|
98
105
|
}
|
|
106
|
+
function locationToAbsoluteUrl(router, location) {
|
|
107
|
+
const search = router.options.stringifySearch?.(location.search) ?? "";
|
|
108
|
+
const pathWithSearch = `${location.pathname}${search && search !== "?" ? search : ""}`;
|
|
109
|
+
return browser.getAbsoluteUrl(pathWithSearch);
|
|
110
|
+
}
|
|
111
|
+
function locationToSpanUrlAttributes(router, location) {
|
|
112
|
+
const absoluteUrl = locationToAbsoluteUrl(router, location);
|
|
113
|
+
return {
|
|
114
|
+
[attributes.URL_PATH]: location.pathname,
|
|
115
|
+
[attributes.URL_FULL]: absoluteUrl
|
|
116
|
+
};
|
|
117
|
+
}
|
|
99
118
|
function routeMatchToParamSpanAttributes(match) {
|
|
100
119
|
if (!match) {
|
|
101
120
|
return {};
|
|
@@ -103,8 +122,8 @@ function routeMatchToParamSpanAttributes(match) {
|
|
|
103
122
|
const paramAttributes = {};
|
|
104
123
|
Object.entries(match.params).forEach(([key, value]) => {
|
|
105
124
|
paramAttributes[`url.path.params.${key}`] = value;
|
|
106
|
-
paramAttributes[
|
|
107
|
-
paramAttributes[
|
|
125
|
+
paramAttributes[attributes.URL_PATH_PARAMETER_KEY.replace("<key>", key)] = value;
|
|
126
|
+
paramAttributes[attributes.PARAMS_KEY.replace("<key>", key)] = value;
|
|
108
127
|
});
|
|
109
128
|
return paramAttributes;
|
|
110
129
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tanstackrouter.js","sources":["../../src/tanstackrouter.ts"],"sourcesContent":["import {\n browserTracingIntegration as originalBrowserTracingIntegration,\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';\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 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 ...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 resolvedMatch = resolveRouteMatch(onResolvedArgs.toLocation.pathname, onResolvedArgs.toLocation.search);\n if (resolvedMatch && resolvedMatch.routeId !== routeMatch?.routeId) {\n pageloadSpan.updateName(resolvedMatch.routeId);\n pageloadSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'route');\n pageloadSpan.setAttributes(routeMatchToParamSpanAttributes(resolvedMatch));\n }\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 const applyRouteMatch = (\n span: NonNullable<typeof inFlightNavigationSpan>,\n match: VendoredTanstackRouterRouteMatch | undefined,\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(routeMatchToParamSpanAttributes(match));\n };\n\n castRouterInstance.subscribe('onBeforeLoad', onBeforeLoadArgs => {\n // Skip the initial pageload (no fromLocation) and no-op reloads (same state).\n if (\n !onBeforeLoadArgs.fromLocation ||\n onBeforeLoadArgs.toLocation.state === onBeforeLoadArgs.fromLocation.state\n ) {\n return;\n }\n\n const routeMatch = resolveRouteMatch(\n onBeforeLoadArgs.toLocation.pathname,\n onBeforeLoadArgs.toLocation.search,\n );\n const fallbackName = WINDOW.location.pathname;\n\n if (inFlightNavigationSpan) {\n // Redirect continuation within the same navigation: keep the span, update the target.\n applyRouteMatch(inFlightNavigationSpan, routeMatch, fallbackName);\n return;\n }\n\n inFlightNavigationSpan = startBrowserTracingNavigationSpan(client, {\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 ...routeMatchToParamSpanAttributes(routeMatch),\n },\n });\n });\n\n castRouterInstance.subscribe('onResolved', onResolvedArgs => {\n const span = inFlightNavigationSpan;\n inFlightNavigationSpan = undefined;\n if (!span) {\n return;\n }\n const resolvedMatch = resolveRouteMatch(onResolvedArgs.toLocation.pathname, onResolvedArgs.toLocation.search);\n if (resolvedMatch) {\n applyRouteMatch(span, resolvedMatch, WINDOW.location.pathname);\n }\n });\n }\n },\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}`] = value;\n paramAttributes[`params.${key}`] = value; // params.[key] is an alias\n });\n\n return paramAttributes;\n}\n"],"names":["originalBrowserTracingIntegration","WINDOW","startBrowserTracingPageLoadSpan","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","startBrowserTracingNavigationSpan"],"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 {\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 { PARAMS_KEY, URL_FULL, URL_PATH, URL_PATH_PARAMETER_KEY, URL_TEMPLATE } 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.replace('<key>', key)] = value;\n paramAttributes[PARAMS_KEY.replace('<key>', 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","PARAMS_KEY"],"mappings":"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"}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"10.
|
|
1
|
+
{"type":"module","version":"10.66.0","sideEffects":false}
|
|
@@ -5,6 +5,7 @@ import { DEBUG_BUILD } from '../debug-build.js';
|
|
|
5
5
|
import { hoistNonReactStatics } from '../hoist-non-react-statics.js';
|
|
6
6
|
import { checkRouteForAsyncHandler } from './lazy-routes.js';
|
|
7
7
|
import { getActiveRootSpan, setNavigationContext, clearNavigationContext, resolveRouteNameAndSource, transactionNameHasWildcard, initializeRouterUtils } from './utils.js';
|
|
8
|
+
import { URL_TEMPLATE } from '@sentry/conventions/attributes';
|
|
8
9
|
|
|
9
10
|
let _useEffect;
|
|
10
11
|
let _useLocation;
|
|
@@ -165,6 +166,9 @@ function updateNavigationSpan(activeRootSpan, location, allRoutes2, forceUpdate
|
|
|
165
166
|
if (isImprovement) {
|
|
166
167
|
activeRootSpan.updateName(name);
|
|
167
168
|
activeRootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
|
|
169
|
+
if (source === "route") {
|
|
170
|
+
activeRootSpan.setAttribute(URL_TEMPLATE, name);
|
|
171
|
+
}
|
|
168
172
|
if (!transactionNameHasWildcard(name) && source === "route") {
|
|
169
173
|
addNonEnumerableProperty(
|
|
170
174
|
activeRootSpan,
|
|
@@ -549,6 +553,9 @@ function handleNavigation(opts) {
|
|
|
549
553
|
} else {
|
|
550
554
|
trackedNav.span.updateName(name);
|
|
551
555
|
trackedNav.span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
|
|
556
|
+
if (source === "route") {
|
|
557
|
+
trackedNav.span.setAttribute(URL_TEMPLATE, name);
|
|
558
|
+
}
|
|
552
559
|
addNonEnumerableProperty(
|
|
553
560
|
trackedNav.span,
|
|
554
561
|
"__sentry_navigation_name_set__",
|
|
@@ -580,7 +587,8 @@ function handleNavigation(opts) {
|
|
|
580
587
|
attributes: {
|
|
581
588
|
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
|
|
582
589
|
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
|
|
583
|
-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.navigation.react.reactrouter${version ? `_v${version}` : ""}
|
|
590
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.navigation.react.reactrouter${version ? `_v${version}` : ""}`,
|
|
591
|
+
...source === "route" && { [URL_TEMPLATE]: placeholderEntry.routeName }
|
|
584
592
|
}
|
|
585
593
|
});
|
|
586
594
|
} catch (e) {
|
|
@@ -646,6 +654,9 @@ function updatePageloadTransaction({
|
|
|
646
654
|
if (activeRootSpan) {
|
|
647
655
|
activeRootSpan.updateName(name);
|
|
648
656
|
activeRootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
|
|
657
|
+
if (source === "route") {
|
|
658
|
+
activeRootSpan.setAttribute(URL_TEMPLATE, name);
|
|
659
|
+
}
|
|
649
660
|
patchSpanEnd(activeRootSpan, location, routes, basename, "pageload");
|
|
650
661
|
}
|
|
651
662
|
} else if (activeRootSpan) {
|
|
@@ -694,6 +705,9 @@ function tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, route
|
|
|
694
705
|
if (isImprovement && spanNotEnded) {
|
|
695
706
|
span.updateName(name);
|
|
696
707
|
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
|
|
708
|
+
if (source === "route") {
|
|
709
|
+
span.setAttribute(URL_TEMPLATE, name);
|
|
710
|
+
}
|
|
697
711
|
}
|
|
698
712
|
} catch (error) {
|
|
699
713
|
DEBUG_BUILD && debug.warn(`Error updating span details before ending: ${error}`);
|