@sentry/react 11.0.0-beta.1 → 11.0.0-rc.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/react-router.js +21 -0
- package/build/cjs/react-router.js.map +1 -0
- package/build/cjs/reactrouter-compat-utils/instrumentation.js +149 -136
- package/build/cjs/reactrouter-compat-utils/instrumentation.js.map +1 -1
- package/build/cjs/reactrouter-compat-utils/utils.js +28 -32
- package/build/cjs/reactrouter-compat-utils/utils.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/react-router.js +16 -0
- package/build/esm/react-router.js.map +1 -0
- package/build/esm/reactrouter-compat-utils/instrumentation.js +151 -138
- package/build/esm/reactrouter-compat-utils/instrumentation.js.map +1 -1
- package/build/esm/reactrouter-compat-utils/utils.js +29 -32
- package/build/esm/reactrouter-compat-utils/utils.js.map +1 -1
- package/build/types/react-router.d.ts +26 -0
- package/build/types/react-router.d.ts.map +1 -0
- package/build/types/reactrouter-compat-utils/index.d.ts +1 -1
- package/build/types/reactrouter-compat-utils/index.d.ts.map +1 -1
- package/build/types/reactrouter-compat-utils/instrumentation.d.ts +9 -5
- package/build/types/reactrouter-compat-utils/instrumentation.d.ts.map +1 -1
- package/build/types/reactrouter-compat-utils/utils.d.ts +5 -10
- package/build/types/reactrouter-compat-utils/utils.d.ts.map +1 -1
- package/build/types/types.d.ts +16 -0
- package/build/types/types.d.ts.map +1 -1
- package/package.json +34 -6
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
import { WINDOW, browserTracingIntegration, startBrowserTracingPageLoadSpan, startBrowserTracingNavigationSpan } from '@sentry/browser';
|
|
2
|
-
import { PAGELOAD_SPAN_NAME_FALLBACK, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, hasSpanStreamingEnabled, debug, addNonEnumerableProperty, spanToJSON, getCurrentScope,
|
|
2
|
+
import { extendIntegration, PAGELOAD_SPAN_NAME_FALLBACK, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, hasSpanStreamingEnabled, debug, getClient, addNonEnumerableProperty, spanToJSON, getCurrentScope, NAVIGATION_SPAN_NAME_FALLBACK } from '@sentry/core';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
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
|
-
import { getActiveRootSpan, setNavigationContext, clearNavigationContext, resolveRouteNameAndSource, transactionNameHasWildcard
|
|
7
|
+
import { getActiveRootSpan, setNavigationContext, clearNavigationContext, resolveRouteNameAndSource, transactionNameHasWildcard } from './utils.js';
|
|
8
8
|
import { SENTRY_OP, SENTRY_SEGMENT_NAME_SOURCE, URL_TEMPLATE } from '@sentry/conventions/attributes';
|
|
9
9
|
import { PAGELOAD, NAVIGATION } from '@sentry/conventions/op';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
let _matchRoutes;
|
|
16
|
-
let _enableAsyncRouteHandlers = false;
|
|
17
|
-
let _lazyRouteTimeout = 3e3;
|
|
18
|
-
let _lazyRouteManifest;
|
|
19
|
-
let _basename = "";
|
|
20
|
-
const CLIENTS_WITH_INSTRUMENT_NAVIGATION = /* @__PURE__ */ new WeakSet();
|
|
11
|
+
const reactRouterConfigByClient = /* @__PURE__ */ new WeakMap();
|
|
12
|
+
function getRouterConfig(client) {
|
|
13
|
+
return client ? reactRouterConfigByClient.get(client) : void 0;
|
|
14
|
+
}
|
|
21
15
|
const useIsomorphicLayoutEffect = WINDOW?.document ? React.useLayoutEffect : React.useEffect;
|
|
22
16
|
const activeNavigationSpans = /* @__PURE__ */ new WeakMap();
|
|
23
17
|
const allRoutes = /* @__PURE__ */ new Set();
|
|
@@ -101,11 +95,11 @@ function resolveDeferredLazyRoutePromise(span) {
|
|
|
101
95
|
}
|
|
102
96
|
}
|
|
103
97
|
}
|
|
104
|
-
function processResolvedRoutes(resolvedRoutes, parentRoute, currentLocation = null, capturedSpan) {
|
|
98
|
+
function processResolvedRoutes(resolvedRoutes, config, parentRoute, currentLocation = null, capturedSpan) {
|
|
105
99
|
resolvedRoutes.forEach((child) => {
|
|
106
100
|
allRoutes.add(child);
|
|
107
|
-
if (
|
|
108
|
-
checkRouteForAsyncHandler(child, processResolvedRoutes);
|
|
101
|
+
if (config.enableAsyncRouteHandlers) {
|
|
102
|
+
checkRouteForAsyncHandler(child, (r, p, l, s) => processResolvedRoutes(r, config, p, l, s));
|
|
109
103
|
}
|
|
110
104
|
});
|
|
111
105
|
if (parentRoute) {
|
|
@@ -134,29 +128,35 @@ function processResolvedRoutes(resolvedRoutes, parentRoute, currentLocation = nu
|
|
|
134
128
|
activeRootSpan: targetSpan,
|
|
135
129
|
location: { pathname: location.pathname },
|
|
136
130
|
routes: Array.from(allRoutes),
|
|
137
|
-
allRoutes: Array.from(allRoutes)
|
|
131
|
+
allRoutes: Array.from(allRoutes),
|
|
132
|
+
config
|
|
138
133
|
});
|
|
139
134
|
} else if (spanOp === "navigation") {
|
|
140
|
-
updateNavigationSpan(targetSpan, location, Array.from(allRoutes), false,
|
|
135
|
+
updateNavigationSpan(targetSpan, location, Array.from(allRoutes), false, config);
|
|
141
136
|
}
|
|
142
137
|
}
|
|
143
138
|
}
|
|
144
139
|
}
|
|
145
|
-
function updateNavigationSpan(activeRootSpan, location, allRoutes2, forceUpdate = false,
|
|
140
|
+
function updateNavigationSpan(activeRootSpan, location, allRoutes2, forceUpdate = false, config) {
|
|
146
141
|
const { name: currentName, end_timestamp, attributes } = spanToJSON(activeRootSpan);
|
|
142
|
+
const spanPathname = activeRootSpan?.__sentry_navigation_pathname__;
|
|
143
|
+
if (spanPathname !== void 0 && spanPathname !== location.pathname) {
|
|
144
|
+
DEBUG_BUILD && debug.log(
|
|
145
|
+
`[React Router] Not renaming the navigation span for "${spanPathname}" with the route of "${location.pathname}"`
|
|
146
|
+
);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
147
149
|
const hasBeenNamed = activeRootSpan?.__sentry_navigation_name_set__;
|
|
148
150
|
const currentNameHasWildcard = currentName && transactionNameHasWildcard(currentName);
|
|
149
151
|
const shouldUpdate = !hasBeenNamed || forceUpdate || currentNameHasWildcard;
|
|
150
152
|
if (shouldUpdate && !end_timestamp) {
|
|
151
|
-
const currentBranches = matchRoutes(allRoutes2, location);
|
|
153
|
+
const currentBranches = config.matchRoutes(allRoutes2, location);
|
|
152
154
|
const [name, source] = resolveRouteNameAndSource(
|
|
153
155
|
location,
|
|
154
156
|
allRoutes2,
|
|
155
157
|
allRoutes2,
|
|
156
158
|
currentBranches || [],
|
|
157
|
-
|
|
158
|
-
_lazyRouteManifest,
|
|
159
|
-
_enableAsyncRouteHandlers
|
|
159
|
+
config
|
|
160
160
|
);
|
|
161
161
|
const currentSource = attributes[SENTRY_SEGMENT_NAME_SOURCE];
|
|
162
162
|
const isImprovement = name && (!currentName || // No current name - always set
|
|
@@ -177,7 +177,7 @@ function updateNavigationSpan(activeRootSpan, location, allRoutes2, forceUpdate
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
|
-
function setupRouterSubscription(router, routes, version,
|
|
180
|
+
function setupRouterSubscription(router, routes, version, activeRootSpan, config) {
|
|
181
181
|
let isInitialPageloadComplete = false;
|
|
182
182
|
let hasSeenPageloadSpan = !!activeRootSpan && spanToJSON(activeRootSpan).attributes[SENTRY_OP] === "pageload";
|
|
183
183
|
let hasSeenPopAfterPageload = false;
|
|
@@ -211,8 +211,8 @@ function setupRouterSubscription(router, routes, version, basename, activeRootSp
|
|
|
211
211
|
routes,
|
|
212
212
|
navigationType: state.historyAction,
|
|
213
213
|
version,
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
allRoutes: Array.from(allRoutes),
|
|
215
|
+
config
|
|
216
216
|
});
|
|
217
217
|
};
|
|
218
218
|
if (state.navigation.state !== "idle") {
|
|
@@ -234,17 +234,19 @@ function setupRouterSubscription(router, routes, version, basename, activeRootSp
|
|
|
234
234
|
});
|
|
235
235
|
}
|
|
236
236
|
function createV6CompatibleWrapCreateBrowserRouter(createRouterFunction, version) {
|
|
237
|
-
if (!_useEffect || !_useLocation || !_useNavigationType || !_matchRoutes) {
|
|
238
|
-
DEBUG_BUILD && debug.warn(
|
|
239
|
-
`reactRouter${version ? `V${version}` : ""}Instrumentation was unable to wrap the \`createRouter\` function because of one or more missing parameters.`
|
|
240
|
-
);
|
|
241
|
-
return createRouterFunction;
|
|
242
|
-
}
|
|
243
237
|
return function(routes, opts) {
|
|
238
|
+
const base = getRouterConfig(getClient());
|
|
239
|
+
if (!base) {
|
|
240
|
+
DEBUG_BUILD && debug.warn(
|
|
241
|
+
`reactRouter${version ? `V${version}` : ""}Instrumentation was unable to wrap the \`createRouter\` function because the React Router browser tracing integration was not set up. Make sure \`Sentry.init()\` runs before the router is created.`
|
|
242
|
+
);
|
|
243
|
+
return createRouterFunction(routes, opts);
|
|
244
|
+
}
|
|
245
|
+
const config = { ...base, basename: opts?.basename || "" };
|
|
244
246
|
addRoutesToAllRoutes(routes);
|
|
245
|
-
if (
|
|
247
|
+
if (config.enableAsyncRouteHandlers) {
|
|
246
248
|
for (const route of routes) {
|
|
247
|
-
checkRouteForAsyncHandler(route, processResolvedRoutes);
|
|
249
|
+
checkRouteForAsyncHandler(route, (r, p, l, s) => processResolvedRoutes(r, config, p, l, s));
|
|
248
250
|
}
|
|
249
251
|
}
|
|
250
252
|
const activeRootSpan = getActiveRootSpan();
|
|
@@ -253,35 +255,35 @@ function createV6CompatibleWrapCreateBrowserRouter(createRouterFunction, version
|
|
|
253
255
|
addNonEnumerableProperty(activeRootSpan, "__sentry_may_have_lazy_routes__", true);
|
|
254
256
|
createDeferredLazyRoutePromise(activeRootSpan);
|
|
255
257
|
}
|
|
256
|
-
const wrappedOpts = wrapPatchRoutesOnNavigation(opts, false, activeRootSpan);
|
|
258
|
+
const wrappedOpts = wrapPatchRoutesOnNavigation(opts, false, activeRootSpan, config);
|
|
257
259
|
const router = createRouterFunction(routes, wrappedOpts);
|
|
258
|
-
const basename = opts?.basename;
|
|
259
260
|
if (router.state.historyAction === "POP" && activeRootSpan) {
|
|
260
261
|
updatePageloadTransaction({
|
|
261
262
|
activeRootSpan,
|
|
262
263
|
location: router.state.location,
|
|
263
264
|
routes,
|
|
264
|
-
|
|
265
|
-
|
|
265
|
+
allRoutes: Array.from(allRoutes),
|
|
266
|
+
config
|
|
266
267
|
});
|
|
267
268
|
}
|
|
268
|
-
|
|
269
|
-
setupRouterSubscription(router, routes, version, basename, activeRootSpan);
|
|
269
|
+
setupRouterSubscription(router, routes, version, activeRootSpan, config);
|
|
270
270
|
return router;
|
|
271
271
|
};
|
|
272
272
|
}
|
|
273
273
|
function createV6CompatibleWrapCreateMemoryRouter(createRouterFunction, version) {
|
|
274
|
-
if (!_useEffect || !_useLocation || !_useNavigationType || !_matchRoutes) {
|
|
275
|
-
DEBUG_BUILD && debug.warn(
|
|
276
|
-
`reactRouter${version ? `V${version}` : ""}Instrumentation was unable to wrap the \`createMemoryRouter\` function because of one or more missing parameters.`
|
|
277
|
-
);
|
|
278
|
-
return createRouterFunction;
|
|
279
|
-
}
|
|
280
274
|
return function(routes, opts) {
|
|
275
|
+
const base = getRouterConfig(getClient());
|
|
276
|
+
if (!base) {
|
|
277
|
+
DEBUG_BUILD && debug.warn(
|
|
278
|
+
`reactRouter${version ? `V${version}` : ""}Instrumentation was unable to wrap the \`createMemoryRouter\` function because the React Router browser tracing integration was not set up. Make sure \`Sentry.init()\` runs before the router is created.`
|
|
279
|
+
);
|
|
280
|
+
return createRouterFunction(routes, opts);
|
|
281
|
+
}
|
|
282
|
+
const config = { ...base, basename: opts?.basename || "" };
|
|
281
283
|
addRoutesToAllRoutes(routes);
|
|
282
|
-
if (
|
|
284
|
+
if (config.enableAsyncRouteHandlers) {
|
|
283
285
|
for (const route of routes) {
|
|
284
|
-
checkRouteForAsyncHandler(route, processResolvedRoutes);
|
|
286
|
+
checkRouteForAsyncHandler(route, (r, p, l, s) => processResolvedRoutes(r, config, p, l, s));
|
|
285
287
|
}
|
|
286
288
|
}
|
|
287
289
|
const memoryActiveRootSpanEarly = getActiveRootSpan();
|
|
@@ -290,9 +292,8 @@ function createV6CompatibleWrapCreateMemoryRouter(createRouterFunction, version)
|
|
|
290
292
|
addNonEnumerableProperty(memoryActiveRootSpanEarly, "__sentry_may_have_lazy_routes__", true);
|
|
291
293
|
createDeferredLazyRoutePromise(memoryActiveRootSpanEarly);
|
|
292
294
|
}
|
|
293
|
-
const wrappedOpts = wrapPatchRoutesOnNavigation(opts, true, memoryActiveRootSpanEarly);
|
|
295
|
+
const wrappedOpts = wrapPatchRoutesOnNavigation(opts, true, memoryActiveRootSpanEarly, config);
|
|
294
296
|
const router = createRouterFunction(routes, wrappedOpts);
|
|
295
|
-
const basename = opts?.basename;
|
|
296
297
|
let initialEntry = void 0;
|
|
297
298
|
const initialEntries = opts?.initialEntries;
|
|
298
299
|
const initialIndex = opts?.initialIndex;
|
|
@@ -306,19 +307,17 @@ function createV6CompatibleWrapCreateMemoryRouter(createRouterFunction, version)
|
|
|
306
307
|
activeRootSpan: memoryActiveRootSpan,
|
|
307
308
|
location,
|
|
308
309
|
routes,
|
|
309
|
-
|
|
310
|
-
|
|
310
|
+
allRoutes: Array.from(allRoutes),
|
|
311
|
+
config
|
|
311
312
|
});
|
|
312
313
|
}
|
|
313
|
-
|
|
314
|
-
setupRouterSubscription(router, routes, version, basename, memoryActiveRootSpan);
|
|
314
|
+
setupRouterSubscription(router, routes, version, memoryActiveRootSpan, config);
|
|
315
315
|
return router;
|
|
316
316
|
};
|
|
317
317
|
}
|
|
318
318
|
function createReactRouterV6CompatibleTracingIntegration(options, version) {
|
|
319
319
|
const integration = browserTracingIntegration({ ...options, instrumentPageLoad: false, instrumentNavigation: false });
|
|
320
320
|
const {
|
|
321
|
-
useEffect,
|
|
322
321
|
useLocation,
|
|
323
322
|
useNavigationType,
|
|
324
323
|
createRoutesFromChildren,
|
|
@@ -330,15 +329,14 @@ function createReactRouterV6CompatibleTracingIntegration(options, version) {
|
|
|
330
329
|
lazyRouteTimeout,
|
|
331
330
|
lazyRouteManifest
|
|
332
331
|
} = options;
|
|
333
|
-
return {
|
|
334
|
-
...integration,
|
|
332
|
+
return extendIntegration(integration, {
|
|
335
333
|
setup(client) {
|
|
336
|
-
integration.setup(client);
|
|
337
334
|
const finalTimeout = options.finalTimeout ?? 3e4;
|
|
338
335
|
const defaultMaxWait = (options.idleTimeout ?? 1e3) * 3;
|
|
339
336
|
const configuredMaxWait = lazyRouteTimeout ?? defaultMaxWait;
|
|
337
|
+
let resolvedLazyRouteTimeout;
|
|
340
338
|
if (configuredMaxWait === Infinity) {
|
|
341
|
-
|
|
339
|
+
resolvedLazyRouteTimeout = finalTimeout;
|
|
342
340
|
DEBUG_BUILD && debug.log(
|
|
343
341
|
"[React Router] lazyRouteTimeout set to Infinity, capping at finalTimeout:",
|
|
344
342
|
finalTimeout,
|
|
@@ -346,7 +344,7 @@ function createReactRouterV6CompatibleTracingIntegration(options, version) {
|
|
|
346
344
|
);
|
|
347
345
|
} else if (Number.isNaN(configuredMaxWait)) {
|
|
348
346
|
DEBUG_BUILD && debug.warn("[React Router] lazyRouteTimeout must be a number, falling back to default:", defaultMaxWait);
|
|
349
|
-
|
|
347
|
+
resolvedLazyRouteTimeout = defaultMaxWait;
|
|
350
348
|
} else if (configuredMaxWait < 0) {
|
|
351
349
|
DEBUG_BUILD && debug.warn(
|
|
352
350
|
"[React Router] lazyRouteTimeout must be non-negative or Infinity, got:",
|
|
@@ -354,21 +352,30 @@ function createReactRouterV6CompatibleTracingIntegration(options, version) {
|
|
|
354
352
|
"falling back to:",
|
|
355
353
|
defaultMaxWait
|
|
356
354
|
);
|
|
357
|
-
|
|
355
|
+
resolvedLazyRouteTimeout = defaultMaxWait;
|
|
358
356
|
} else {
|
|
359
|
-
|
|
357
|
+
resolvedLazyRouteTimeout = configuredMaxWait;
|
|
358
|
+
}
|
|
359
|
+
if (typeof useLocation === "function" && typeof useNavigationType === "function" && typeof createRoutesFromChildren === "function" && typeof matchRoutes === "function") {
|
|
360
|
+
reactRouterConfigByClient.set(client, {
|
|
361
|
+
useLocation,
|
|
362
|
+
useNavigationType,
|
|
363
|
+
createRoutesFromChildren,
|
|
364
|
+
matchRoutes,
|
|
365
|
+
stripBasename: stripBasename || false,
|
|
366
|
+
enableAsyncRouteHandlers,
|
|
367
|
+
instrumentNavigation,
|
|
368
|
+
lazyRouteTimeout: resolvedLazyRouteTimeout,
|
|
369
|
+
lazyRouteManifest,
|
|
370
|
+
basename: ""
|
|
371
|
+
});
|
|
372
|
+
} else {
|
|
373
|
+
DEBUG_BUILD && debug.warn(
|
|
374
|
+
"[React Router] Skipping route instrumentation because `useLocation`, `useNavigationType`, `createRoutesFromChildren` or `matchRoutes` was not provided. Pass them to `reactRouterBrowserTracingIntegration`, or import it from `@sentry/react/react-router` to have them supplied automatically."
|
|
375
|
+
);
|
|
360
376
|
}
|
|
361
|
-
_useEffect = useEffect;
|
|
362
|
-
_useLocation = useLocation;
|
|
363
|
-
_useNavigationType = useNavigationType;
|
|
364
|
-
_matchRoutes = matchRoutes;
|
|
365
|
-
_createRoutesFromChildren = createRoutesFromChildren;
|
|
366
|
-
_enableAsyncRouteHandlers = enableAsyncRouteHandlers;
|
|
367
|
-
_lazyRouteManifest = lazyRouteManifest;
|
|
368
|
-
initializeRouterUtils(matchRoutes, stripBasename || false);
|
|
369
377
|
},
|
|
370
378
|
afterAllSetup(client) {
|
|
371
|
-
integration.afterAllSetup(client);
|
|
372
379
|
const initPathName = WINDOW.location?.pathname;
|
|
373
380
|
if (instrumentPageLoad && initPathName) {
|
|
374
381
|
startBrowserTracingPageLoadSpan(client, {
|
|
@@ -382,25 +389,14 @@ function createReactRouterV6CompatibleTracingIntegration(options, version) {
|
|
|
382
389
|
}
|
|
383
390
|
});
|
|
384
391
|
}
|
|
385
|
-
if (instrumentNavigation) {
|
|
386
|
-
CLIENTS_WITH_INSTRUMENT_NAVIGATION.add(client);
|
|
387
|
-
}
|
|
388
392
|
}
|
|
389
|
-
};
|
|
393
|
+
});
|
|
390
394
|
}
|
|
391
395
|
function createV6CompatibleWrapUseRoutes(origUseRoutes, version) {
|
|
392
|
-
|
|
393
|
-
DEBUG_BUILD && debug.warn(
|
|
394
|
-
"reactRouterV6Instrumentation was unable to wrap `useRoutes` because of one or more missing parameters."
|
|
395
|
-
);
|
|
396
|
-
return origUseRoutes;
|
|
397
|
-
}
|
|
398
|
-
const SentryRoutes = (props) => {
|
|
396
|
+
const RouteReporter = ({ config, routes, locationArg }) => {
|
|
399
397
|
const isMountRenderPass = React.useRef(true);
|
|
400
|
-
const
|
|
401
|
-
const
|
|
402
|
-
const location = _useLocation();
|
|
403
|
-
const navigationType = _useNavigationType();
|
|
398
|
+
const location = config.useLocation();
|
|
399
|
+
const navigationType = config.useNavigationType();
|
|
404
400
|
const stableLocationParam = typeof locationArg === "string" || locationArg?.pathname ? locationArg : location;
|
|
405
401
|
useIsomorphicLayoutEffect(() => {
|
|
406
402
|
const added = addRoutesToAllRoutes(routes);
|
|
@@ -413,7 +409,8 @@ function createV6CompatibleWrapUseRoutes(origUseRoutes, version) {
|
|
|
413
409
|
activeRootSpan: getActiveRootSpan(),
|
|
414
410
|
location: normalizedLocation,
|
|
415
411
|
routes,
|
|
416
|
-
allRoutes: Array.from(allRoutes)
|
|
412
|
+
allRoutes: Array.from(allRoutes),
|
|
413
|
+
config
|
|
417
414
|
});
|
|
418
415
|
isMountRenderPass.current = false;
|
|
419
416
|
} else {
|
|
@@ -422,17 +419,26 @@ function createV6CompatibleWrapUseRoutes(origUseRoutes, version) {
|
|
|
422
419
|
routes,
|
|
423
420
|
navigationType,
|
|
424
421
|
version,
|
|
425
|
-
allRoutes: Array.from(allRoutes)
|
|
422
|
+
allRoutes: Array.from(allRoutes),
|
|
423
|
+
config
|
|
426
424
|
});
|
|
427
425
|
}
|
|
428
426
|
}, [navigationType, stableLocationParam]);
|
|
429
|
-
return
|
|
427
|
+
return null;
|
|
428
|
+
};
|
|
429
|
+
const SentryRoutesWrapper = ({
|
|
430
|
+
routes,
|
|
431
|
+
locationArg
|
|
432
|
+
}) => {
|
|
433
|
+
const config = getRouterConfig(getClient());
|
|
434
|
+
const routesElement = origUseRoutes(routes, locationArg);
|
|
435
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, routesElement, config ? /* @__PURE__ */ React.createElement(RouteReporter, { config, routes, locationArg }) : null);
|
|
430
436
|
};
|
|
431
437
|
return (routes, locationArg) => {
|
|
432
|
-
return /* @__PURE__ */ React.createElement(
|
|
438
|
+
return /* @__PURE__ */ React.createElement(SentryRoutesWrapper, { routes, locationArg });
|
|
433
439
|
};
|
|
434
440
|
}
|
|
435
|
-
function wrapPatchRoutesOnNavigation(opts, isMemoryRouter
|
|
441
|
+
function wrapPatchRoutesOnNavigation(opts, isMemoryRouter, capturedSpan, config) {
|
|
436
442
|
if (!opts || !("patchRoutesOnNavigation" in opts) || typeof opts.patchRoutesOnNavigation !== "function") {
|
|
437
443
|
return opts || {};
|
|
438
444
|
}
|
|
@@ -471,7 +477,7 @@ function wrapPatchRoutesOnNavigation(opts, isMemoryRouter = false, capturedSpan)
|
|
|
471
477
|
{ pathname: targetPath, search: "", hash: "", state: null, key: "default" },
|
|
472
478
|
Array.from(allRoutes),
|
|
473
479
|
true,
|
|
474
|
-
|
|
480
|
+
config
|
|
475
481
|
);
|
|
476
482
|
}
|
|
477
483
|
return originalPatch(routeId, children);
|
|
@@ -499,7 +505,7 @@ function wrapPatchRoutesOnNavigation(opts, isMemoryRouter = false, capturedSpan)
|
|
|
499
505
|
{ pathname, search: "", hash: "", state: null, key: "default" },
|
|
500
506
|
Array.from(allRoutes),
|
|
501
507
|
false,
|
|
502
|
-
|
|
508
|
+
config
|
|
503
509
|
);
|
|
504
510
|
}
|
|
505
511
|
}
|
|
@@ -513,10 +519,10 @@ function wrapPatchRoutesOnNavigation(opts, isMemoryRouter = false, capturedSpan)
|
|
|
513
519
|
};
|
|
514
520
|
}
|
|
515
521
|
function handleNavigation(opts) {
|
|
516
|
-
const { location, routes, navigationType, version,
|
|
517
|
-
const branches = Array.isArray(matches) ? matches :
|
|
522
|
+
const { location, routes, navigationType, version, config, matches, allRoutes: allRoutes2 } = opts;
|
|
523
|
+
const branches = Array.isArray(matches) ? matches : config.matchRoutes(allRoutes2 || routes, location, config.basename);
|
|
518
524
|
const client = getClient();
|
|
519
|
-
if (!client || !
|
|
525
|
+
if (!client || !config.instrumentNavigation) {
|
|
520
526
|
return;
|
|
521
527
|
}
|
|
522
528
|
const activeRootSpan = getActiveRootSpan();
|
|
@@ -529,9 +535,7 @@ function handleNavigation(opts) {
|
|
|
529
535
|
allRoutes2 || routes,
|
|
530
536
|
allRoutes2 || routes,
|
|
531
537
|
branches,
|
|
532
|
-
|
|
533
|
-
_lazyRouteManifest,
|
|
534
|
-
_enableAsyncRouteHandlers
|
|
538
|
+
config
|
|
535
539
|
);
|
|
536
540
|
const locationKey = computeLocationKey(location);
|
|
537
541
|
const trackedNav = activeNavigationSpans.get(client);
|
|
@@ -589,6 +593,7 @@ function handleNavigation(opts) {
|
|
|
589
593
|
throw e;
|
|
590
594
|
}
|
|
591
595
|
if (navigationSpan) {
|
|
596
|
+
addNonEnumerableProperty(navigationSpan, "__sentry_navigation_pathname__", location.pathname);
|
|
592
597
|
activeNavigationSpans.set(client, {
|
|
593
598
|
span: navigationSpan,
|
|
594
599
|
routeName: placeholderEntry.routeName,
|
|
@@ -596,7 +601,7 @@ function handleNavigation(opts) {
|
|
|
596
601
|
pathname: location.pathname,
|
|
597
602
|
locationKey
|
|
598
603
|
});
|
|
599
|
-
patchSpanEnd(navigationSpan, location, routes,
|
|
604
|
+
patchSpanEnd(navigationSpan, location, routes, "navigation", config);
|
|
600
605
|
} else {
|
|
601
606
|
activeNavigationSpans.delete(client);
|
|
602
607
|
}
|
|
@@ -636,20 +641,18 @@ function updatePageloadTransaction({
|
|
|
636
641
|
activeRootSpan,
|
|
637
642
|
location,
|
|
638
643
|
routes,
|
|
644
|
+
config,
|
|
639
645
|
matches,
|
|
640
|
-
basename,
|
|
641
646
|
allRoutes: allRoutes2
|
|
642
647
|
}) {
|
|
643
|
-
const branches = Array.isArray(matches) ? matches :
|
|
648
|
+
const branches = Array.isArray(matches) ? matches : config.matchRoutes(allRoutes2 || routes, location, config.basename);
|
|
644
649
|
if (branches) {
|
|
645
650
|
const [name, source] = resolveRouteNameAndSource(
|
|
646
651
|
location,
|
|
647
652
|
allRoutes2 || routes,
|
|
648
653
|
allRoutes2 || routes,
|
|
649
654
|
branches,
|
|
650
|
-
|
|
651
|
-
_lazyRouteManifest,
|
|
652
|
-
_enableAsyncRouteHandlers
|
|
655
|
+
config
|
|
653
656
|
);
|
|
654
657
|
getCurrentScope().setTransactionName(name || "/");
|
|
655
658
|
if (activeRootSpan) {
|
|
@@ -660,10 +663,10 @@ function updatePageloadTransaction({
|
|
|
660
663
|
if (source === "route") {
|
|
661
664
|
activeRootSpan.setAttribute(URL_TEMPLATE, name);
|
|
662
665
|
}
|
|
663
|
-
patchSpanEnd(activeRootSpan, location, routes,
|
|
666
|
+
patchSpanEnd(activeRootSpan, location, routes, "pageload", config);
|
|
664
667
|
}
|
|
665
668
|
} else if (activeRootSpan) {
|
|
666
|
-
patchSpanEnd(activeRootSpan, location, routes,
|
|
669
|
+
patchSpanEnd(activeRootSpan, location, routes, "pageload", config);
|
|
667
670
|
}
|
|
668
671
|
}
|
|
669
672
|
function shouldUpdateWildcardSpanName(currentName, currentSource, newName, newSource, allowNoCurrentName = false) {
|
|
@@ -682,7 +685,7 @@ function shouldUpdateWildcardSpanName(currentName, currentSource, newName, newSo
|
|
|
682
685
|
}
|
|
683
686
|
return false;
|
|
684
687
|
}
|
|
685
|
-
function tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes,
|
|
688
|
+
function tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes, spanType, allRoutes2, config) {
|
|
686
689
|
try {
|
|
687
690
|
const currentSource = spanJson.attributes[SENTRY_SEGMENT_NAME_SOURCE];
|
|
688
691
|
if (currentSource === "route" && currentName && !transactionNameHasWildcard(currentName)) {
|
|
@@ -690,19 +693,11 @@ function tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, route
|
|
|
690
693
|
}
|
|
691
694
|
const currentAllRoutes = Array.from(allRoutes2);
|
|
692
695
|
const routesToUse = currentAllRoutes.length > 0 ? currentAllRoutes : routes;
|
|
693
|
-
const branches =
|
|
696
|
+
const branches = config.matchRoutes(routesToUse, location, config.basename);
|
|
694
697
|
if (!branches) {
|
|
695
698
|
return;
|
|
696
699
|
}
|
|
697
|
-
const [name, source] = resolveRouteNameAndSource(
|
|
698
|
-
location,
|
|
699
|
-
routesToUse,
|
|
700
|
-
routesToUse,
|
|
701
|
-
branches,
|
|
702
|
-
basename,
|
|
703
|
-
_lazyRouteManifest,
|
|
704
|
-
_enableAsyncRouteHandlers
|
|
705
|
-
);
|
|
700
|
+
const [name, source] = resolveRouteNameAndSource(location, routesToUse, routesToUse, branches, config);
|
|
706
701
|
const isImprovement = shouldUpdateWildcardSpanName(currentName, currentSource, name, source, true);
|
|
707
702
|
const spanNotEnded = spanType === "pageload" || !spanJson.end_timestamp;
|
|
708
703
|
if (isImprovement && spanNotEnded) {
|
|
@@ -719,7 +714,7 @@ function tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, route
|
|
|
719
714
|
DEBUG_BUILD && debug.warn(`Error updating span details before ending: ${error}`);
|
|
720
715
|
}
|
|
721
716
|
}
|
|
722
|
-
function patchSpanEnd(span, location, routes,
|
|
717
|
+
function patchSpanEnd(span, location, routes, spanType, config) {
|
|
723
718
|
const patchedPropertyName = `__sentry_${spanType}_end_patched__`;
|
|
724
719
|
const hasEndBeenPatched = span?.[patchedPropertyName];
|
|
725
720
|
if (hasEndBeenPatched || !span.end) {
|
|
@@ -750,18 +745,18 @@ function patchSpanEnd(span, location, routes, basename, spanType) {
|
|
|
750
745
|
const hasPendingOrMayHaveLazyRoutes = pendingPromises && pendingPromises.size > 0 || mayHaveLazyRoutes;
|
|
751
746
|
const shouldWaitForLazyRoutes = hasPendingOrMayHaveLazyRoutes && currentName && (transactionNameHasWildcard(currentName) || currentSource !== "route");
|
|
752
747
|
if (shouldWaitForLazyRoutes) {
|
|
753
|
-
if (
|
|
754
|
-
tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes,
|
|
748
|
+
if (config.lazyRouteTimeout === 0) {
|
|
749
|
+
tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes, spanType, allRoutes, config);
|
|
755
750
|
cleanupNavigationSpan();
|
|
756
751
|
originalEnd(endTimestamp);
|
|
757
752
|
return;
|
|
758
753
|
}
|
|
759
|
-
const timeoutPromise = new Promise((r) => setTimeout(r,
|
|
754
|
+
const timeoutPromise = new Promise((r) => setTimeout(r, config.lazyRouteTimeout));
|
|
760
755
|
let waitPromise;
|
|
761
756
|
if (pendingPromises && pendingPromises.size > 0) {
|
|
762
757
|
const allSettled = Promise.allSettled(pendingPromises).then(() => {
|
|
763
758
|
});
|
|
764
|
-
waitPromise =
|
|
759
|
+
waitPromise = config.lazyRouteTimeout === Infinity ? allSettled : Promise.race([allSettled, timeoutPromise]);
|
|
765
760
|
} else {
|
|
766
761
|
waitPromise = timeoutPromise;
|
|
767
762
|
}
|
|
@@ -773,9 +768,9 @@ function patchSpanEnd(span, location, routes, basename, spanType) {
|
|
|
773
768
|
updatedSpanJson.name,
|
|
774
769
|
location,
|
|
775
770
|
routes,
|
|
776
|
-
basename,
|
|
777
771
|
spanType,
|
|
778
|
-
allRoutes
|
|
772
|
+
allRoutes,
|
|
773
|
+
config
|
|
779
774
|
);
|
|
780
775
|
cleanupNavigationSpan();
|
|
781
776
|
originalEnd(endTimestamp);
|
|
@@ -785,24 +780,23 @@ function patchSpanEnd(span, location, routes, basename, spanType) {
|
|
|
785
780
|
});
|
|
786
781
|
return;
|
|
787
782
|
}
|
|
788
|
-
tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes,
|
|
783
|
+
tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes, spanType, allRoutes, config);
|
|
789
784
|
cleanupNavigationSpan();
|
|
790
785
|
originalEnd(endTimestamp);
|
|
791
786
|
};
|
|
792
787
|
addNonEnumerableProperty(span, patchedPropertyName, true);
|
|
793
788
|
}
|
|
794
789
|
function createV6CompatibleWithSentryReactRouterRouting(Routes, version) {
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
return Routes;
|
|
800
|
-
}
|
|
801
|
-
const SentryRoutes = (props) => {
|
|
790
|
+
const RouteReporter = ({
|
|
791
|
+
config,
|
|
792
|
+
routeChildren
|
|
793
|
+
}) => {
|
|
802
794
|
const isMountRenderPass = React.useRef(true);
|
|
803
|
-
const location =
|
|
804
|
-
const navigationType =
|
|
805
|
-
const routes =
|
|
795
|
+
const location = config.useLocation();
|
|
796
|
+
const navigationType = config.useNavigationType();
|
|
797
|
+
const routes = config.createRoutesFromChildren(
|
|
798
|
+
routeChildren
|
|
799
|
+
);
|
|
806
800
|
useIsomorphicLayoutEffect(() => {
|
|
807
801
|
const added = addRoutesToAllRoutes(routes);
|
|
808
802
|
return () => removeRoutesFromAllRoutes(added);
|
|
@@ -814,17 +808,36 @@ function createV6CompatibleWithSentryReactRouterRouting(Routes, version) {
|
|
|
814
808
|
activeRootSpan: getActiveRootSpan(),
|
|
815
809
|
location,
|
|
816
810
|
routes,
|
|
817
|
-
allRoutes: Array.from(allRoutes)
|
|
811
|
+
allRoutes: Array.from(allRoutes),
|
|
812
|
+
config
|
|
818
813
|
});
|
|
819
814
|
isMountRenderPass.current = false;
|
|
820
815
|
} else {
|
|
821
|
-
handleNavigation({
|
|
816
|
+
handleNavigation({
|
|
817
|
+
location,
|
|
818
|
+
routes,
|
|
819
|
+
navigationType,
|
|
820
|
+
version,
|
|
821
|
+
allRoutes: Array.from(allRoutes),
|
|
822
|
+
config
|
|
823
|
+
});
|
|
822
824
|
}
|
|
823
825
|
},
|
|
824
826
|
// Re-run only on location/navigation changes, not children changes
|
|
825
827
|
[location, navigationType]
|
|
826
828
|
);
|
|
827
|
-
return
|
|
829
|
+
return null;
|
|
830
|
+
};
|
|
831
|
+
const SentryRoutes = (props) => {
|
|
832
|
+
const config = getRouterConfig(getClient());
|
|
833
|
+
return /* @__PURE__ */ React.createElement(
|
|
834
|
+
React.Fragment,
|
|
835
|
+
null,
|
|
836
|
+
// @ts-expect-error Setting more specific React Component typing for `R` generic above
|
|
837
|
+
// will break advanced type inference done by react router params
|
|
838
|
+
/* @__PURE__ */ React.createElement(Routes, { ...props }),
|
|
839
|
+
config ? /* @__PURE__ */ React.createElement(RouteReporter, { config, routeChildren: props.children }) : null
|
|
840
|
+
);
|
|
828
841
|
};
|
|
829
842
|
hoistNonReactStatics(SentryRoutes, Routes);
|
|
830
843
|
return SentryRoutes;
|