@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.
@@ -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, getClient, NAVIGATION_SPAN_NAME_FALLBACK } from '@sentry/core';
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, initializeRouterUtils } from './utils.js';
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
- let _useEffect;
12
- let _useLocation;
13
- let _useNavigationType;
14
- let _createRoutesFromChildren;
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 (_enableAsyncRouteHandlers) {
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, _matchRoutes);
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, matchRoutes) {
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
- _basename,
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, basename, activeRootSpan) {
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
- basename,
215
- allRoutes: Array.from(allRoutes)
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 (_enableAsyncRouteHandlers) {
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
- basename,
265
- allRoutes: Array.from(allRoutes)
265
+ allRoutes: Array.from(allRoutes),
266
+ config
266
267
  });
267
268
  }
268
- _basename = basename || "";
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 (_enableAsyncRouteHandlers) {
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
- basename,
310
- allRoutes: Array.from(allRoutes)
310
+ allRoutes: Array.from(allRoutes),
311
+ config
311
312
  });
312
313
  }
313
- _basename = basename || "";
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
- _lazyRouteTimeout = finalTimeout;
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
- _lazyRouteTimeout = defaultMaxWait;
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
- _lazyRouteTimeout = defaultMaxWait;
355
+ resolvedLazyRouteTimeout = defaultMaxWait;
358
356
  } else {
359
- _lazyRouteTimeout = configuredMaxWait;
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
- if (!_useEffect || !_useLocation || !_useNavigationType || !_matchRoutes) {
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 { routes, locationArg } = props;
401
- const Routes = origUseRoutes(routes, locationArg);
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 Routes;
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(SentryRoutes, { routes, locationArg });
438
+ return /* @__PURE__ */ React.createElement(SentryRoutesWrapper, { routes, locationArg });
433
439
  };
434
440
  }
435
- function wrapPatchRoutesOnNavigation(opts, isMemoryRouter = false, capturedSpan) {
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
- _matchRoutes
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
- _matchRoutes
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, matches, basename, allRoutes: allRoutes2 } = opts;
517
- const branches = Array.isArray(matches) ? matches : _matchRoutes(allRoutes2 || routes, location, basename);
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 || !CLIENTS_WITH_INSTRUMENT_NAVIGATION.has(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
- basename,
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, basename, "navigation");
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 : _matchRoutes(allRoutes2 || routes, location, basename);
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
- basename,
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, basename, "pageload");
666
+ patchSpanEnd(activeRootSpan, location, routes, "pageload", config);
664
667
  }
665
668
  } else if (activeRootSpan) {
666
- patchSpanEnd(activeRootSpan, location, routes, basename, "pageload");
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, basename, spanType, allRoutes2) {
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 = _matchRoutes(routesToUse, location, basename);
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, basename, spanType) {
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 (_lazyRouteTimeout === 0) {
754
- tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes, basename, spanType, allRoutes);
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, _lazyRouteTimeout));
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 = _lazyRouteTimeout === Infinity ? allSettled : Promise.race([allSettled, timeoutPromise]);
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, basename, spanType, allRoutes);
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
- if (!_useEffect || !_useLocation || !_useNavigationType || !_createRoutesFromChildren || !_matchRoutes) {
796
- DEBUG_BUILD && debug.warn(`reactRouterV6Instrumentation was unable to wrap Routes because of one or more missing parameters.
797
- useEffect: ${_useEffect}. useLocation: ${_useLocation}. useNavigationType: ${_useNavigationType}.
798
- createRoutesFromChildren: ${_createRoutesFromChildren}. matchRoutes: ${_matchRoutes}.`);
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 = _useLocation();
804
- const navigationType = _useNavigationType();
805
- const routes = _createRoutesFromChildren(props.children);
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({ location, routes, navigationType, version, allRoutes: Array.from(allRoutes) });
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 /* @__PURE__ */ React.createElement(Routes, { ...props });
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;