Skip to content

Commit 43b79af

Browse files
committed
Return to updateNavigationSpan
1 parent ad11220 commit 43b79af

File tree

4 files changed

+70
-63
lines changed

4 files changed

+70
-63
lines changed

packages/react/src/reactrouter-compat-utils/index.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ export {
1111
createNewNavigationSpan,
1212
addResolvedRoutesToParent,
1313
processResolvedRoutes,
14+
updateNavigationSpan,
1415
} from './instrumentation';
1516

1617
// Utility exports
1718
export {
1819
initializeRouterUtils,
1920
getGlobalLocation,
21+
getGlobalPathname,
2022
prefixWithSlash,
2123
rebuildRoutePathFromAllRoutes,
2224
locationIsInsideDescendantRoute,
@@ -28,9 +30,4 @@ export {
2830
} from './utils';
2931

3032
// Lazy route exports
31-
export {
32-
updateNavigationSpanWithLazyRoutes,
33-
createAsyncHandlerProxy,
34-
handleAsyncHandlerResult,
35-
checkRouteForAsyncHandler,
36-
} from './lazy-routes';
33+
export { createAsyncHandlerProxy, handleAsyncHandlerResult, checkRouteForAsyncHandler } from './lazy-routes';

packages/react/src/reactrouter-compat-utils/instrumentation.tsx

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ import type {
3939
UseNavigationType,
4040
UseRoutes,
4141
} from '../types';
42-
import { checkRouteForAsyncHandler, updateNavigationSpanWithLazyRoutes } from './lazy-routes';
42+
import { checkRouteForAsyncHandler } from './lazy-routes';
4343
import {
4444
getGlobalLocation,
45+
getGlobalPathname,
4546
getNormalizedName,
4647
initializeRouterUtils,
4748
locationIsInsideDescendantRoute,
@@ -59,6 +60,53 @@ let _enableAsyncRouteHandlers: boolean = false;
5960

6061
const CLIENTS_WITH_INSTRUMENT_NAVIGATION = new WeakSet<Client>();
6162

63+
/**
64+
* Updates a navigation span with the correct route name after lazy routes have been loaded.
65+
*/
66+
export function updateNavigationSpan(
67+
activeRootSpan: Span,
68+
location: Location,
69+
allRoutes: RouteObject[],
70+
forceUpdate = false,
71+
matchRoutes: MatchRoutes,
72+
): void {
73+
// Check if this span has already been named to avoid multiple updates
74+
// But allow updates if this is a forced update (e.g., when lazy routes are loaded)
75+
const hasBeenNamed =
76+
!forceUpdate &&
77+
(
78+
activeRootSpan as {
79+
__sentry_navigation_name_set__?: boolean;
80+
}
81+
)?.__sentry_navigation_name_set__;
82+
83+
if (!hasBeenNamed) {
84+
// Get fresh branches for the current location with all loaded routes
85+
const currentBranches = matchRoutes(allRoutes, location);
86+
const [name, source] = resolveRouteNameAndSource(
87+
location,
88+
allRoutes,
89+
allRoutes,
90+
(currentBranches as RouteMatch[]) || [],
91+
'',
92+
);
93+
94+
// Only update if we have a valid name and the span hasn't finished
95+
const spanJson = spanToJSON(activeRootSpan);
96+
if (name && !spanJson.timestamp) {
97+
activeRootSpan.updateName(name);
98+
activeRootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
99+
100+
// Mark this span as having its name set to prevent future updates
101+
addNonEnumerableProperty(
102+
activeRootSpan as { __sentry_navigation_name_set__?: boolean },
103+
'__sentry_navigation_name_set__',
104+
true,
105+
);
106+
}
107+
}
108+
}
109+
62110
export interface ReactRouterOptions {
63111
useEffect: UseEffect;
64112
useLocation: UseLocation;
@@ -131,7 +179,7 @@ export function processResolvedRoutes(
131179
);
132180
} else if (spanOp === 'navigation') {
133181
// For navigation spans, update the name with the newly loaded routes
134-
updateNavigationSpanWithLazyRoutes(activeRootSpan, location, Array.from(allRoutes), false, _matchRoutes);
182+
updateNavigationSpan(activeRootSpan, location, Array.from(allRoutes), false, _matchRoutes);
135183
}
136184
}
137185
}
@@ -162,7 +210,7 @@ function wrapPatchRoutesOnNavigation(
162210
addRoutesToAllRoutes(children);
163211
const activeRootSpan = getActiveRootSpan();
164212
if (activeRootSpan && (spanToJSON(activeRootSpan) as { op?: string }).op === 'navigation') {
165-
updateNavigationSpanWithLazyRoutes(
213+
updateNavigationSpan(
166214
activeRootSpan,
167215
{
168216
pathname: targetPath,
@@ -188,9 +236,9 @@ function wrapPatchRoutesOnNavigation(
188236
if (activeRootSpan && (spanToJSON(activeRootSpan) as { op?: string }).op === 'navigation') {
189237
// For memory routers, we don't have a reliable way to get the current pathname
190238
// without accessing window.location, so we'll use targetPath for both cases
191-
const pathname = targetPath || (isMemoryRouter ? getGlobalLocation()?.pathname : undefined);
239+
const pathname = targetPath || (isMemoryRouter ? getGlobalPathname() : undefined);
192240
if (pathname) {
193-
updateNavigationSpanWithLazyRoutes(
241+
updateNavigationSpan(
194242
activeRootSpan,
195243
{
196244
pathname,
@@ -421,7 +469,7 @@ export function createReactRouterV6CompatibleTracingIntegration(
421469
afterAllSetup(client) {
422470
integration.afterAllSetup(client);
423471

424-
const initPathName = getGlobalLocation()?.pathname;
472+
const initPathName = getGlobalPathname();
425473
if (instrumentPageLoad && initPathName) {
426474
startBrowserTracingPageLoadSpan(client, {
427475
name: initPathName,

packages/react/src/reactrouter-compat-utils/lazy-routes.tsx

Lines changed: 2 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,6 @@
1-
import type { Span } from '@sentry/core';
2-
import { addNonEnumerableProperty, debug, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, spanToJSON } from '@sentry/core';
1+
import { addNonEnumerableProperty, debug } from '@sentry/core';
32
import { DEBUG_BUILD } from '../debug-build';
4-
import type { Location, MatchRoutes, RouteMatch, RouteObject } from '../types';
5-
import { resolveRouteNameAndSource } from './utils';
6-
7-
/**
8-
* Updates a navigation span with the correct route name after lazy routes have been loaded.
9-
*/
10-
export function updateNavigationSpanWithLazyRoutes(
11-
activeRootSpan: Span,
12-
location: Location,
13-
allRoutes: RouteObject[],
14-
forceUpdate = false,
15-
matchRoutes: MatchRoutes,
16-
): void {
17-
// Check if this span has already been named to avoid multiple updates
18-
// But allow updates if this is a forced update (e.g., when lazy routes are loaded)
19-
const hasBeenNamed =
20-
!forceUpdate &&
21-
(
22-
activeRootSpan as {
23-
__sentry_navigation_name_set__?: boolean;
24-
}
25-
)?.__sentry_navigation_name_set__;
26-
27-
if (!hasBeenNamed) {
28-
// Get fresh branches for the current location with all loaded routes
29-
const currentBranches = matchRoutes(allRoutes, location);
30-
const [name, source] = resolveRouteNameAndSource(
31-
location,
32-
allRoutes,
33-
allRoutes,
34-
(currentBranches as RouteMatch[]) || [],
35-
'',
36-
);
37-
38-
// Only update if we have a valid name and the span hasn't finished
39-
const spanJson = spanToJSON(activeRootSpan);
40-
if (name && !spanJson.timestamp) {
41-
activeRootSpan.updateName(name);
42-
activeRootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
43-
44-
// Mark this span as having its name set to prevent future updates
45-
addNonEnumerableProperty(
46-
activeRootSpan as { __sentry_navigation_name_set__?: boolean },
47-
'__sentry_navigation_name_set__',
48-
true,
49-
);
50-
}
51-
}
52-
}
3+
import type { Location, RouteObject } from '../types';
534

545
/**
556
* Creates a proxy wrapper for an async handler function.

packages/react/src/reactrouter-compat-utils/utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ export function getGlobalLocation(): Location | undefined {
2929
return undefined;
3030
}
3131

32+
/**
33+
* Gets the pathname from the window object in browser environments.
34+
* Returns undefined if window is not available.
35+
*/
36+
export function getGlobalPathname(): string | undefined {
37+
if (typeof WINDOW !== 'undefined') {
38+
return WINDOW.location?.pathname;
39+
}
40+
return undefined;
41+
}
42+
3243
// Helper functions
3344
function pickPath(match: RouteMatch): string {
3445
return trimWildcard(match.route.path || '');

0 commit comments

Comments
 (0)