@sentry/react 11.0.0-alpha.0 → 11.0.0-alpha.2

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.
Files changed (34) hide show
  1. package/build/cjs/profiler.js +12 -15
  2. package/build/cjs/profiler.js.map +1 -1
  3. package/build/cjs/reactrouter-compat-utils/instrumentation.js +43 -33
  4. package/build/cjs/reactrouter-compat-utils/instrumentation.js.map +1 -1
  5. package/build/cjs/reactrouter-compat-utils/utils.js +2 -1
  6. package/build/cjs/reactrouter-compat-utils/utils.js.map +1 -1
  7. package/build/cjs/reactrouter.js +8 -6
  8. package/build/cjs/reactrouter.js.map +1 -1
  9. package/build/cjs/reactrouterv3.js +6 -4
  10. package/build/cjs/reactrouterv3.js.map +1 -1
  11. package/build/cjs/tanstackrouter.js +20 -9
  12. package/build/cjs/tanstackrouter.js.map +1 -1
  13. package/build/esm/package.json +1 -1
  14. package/build/esm/profiler.js +14 -17
  15. package/build/esm/profiler.js.map +1 -1
  16. package/build/esm/reactrouter-compat-utils/instrumentation.js +45 -35
  17. package/build/esm/reactrouter-compat-utils/instrumentation.js.map +1 -1
  18. package/build/esm/reactrouter-compat-utils/utils.js +2 -1
  19. package/build/esm/reactrouter-compat-utils/utils.js.map +1 -1
  20. package/build/esm/reactrouter.js +10 -8
  21. package/build/esm/reactrouter.js.map +1 -1
  22. package/build/esm/reactrouterv3.js +8 -6
  23. package/build/esm/reactrouterv3.js.map +1 -1
  24. package/build/esm/tanstackrouter.js +23 -12
  25. package/build/esm/tanstackrouter.js.map +1 -1
  26. package/build/types/profiler.d.ts.map +1 -1
  27. package/build/types/reactrouter-compat-utils/instrumentation.d.ts.map +1 -1
  28. package/build/types/reactrouter-compat-utils/utils.d.ts.map +1 -1
  29. package/build/types/reactrouter.d.ts.map +1 -1
  30. package/build/types/reactrouterv3.d.ts.map +1 -1
  31. package/build/types/tanstackrouter.d.ts.map +1 -1
  32. package/build/types/vendor/tanstackrouter-types.d.ts +1 -0
  33. package/build/types/vendor/tanstackrouter-types.d.ts.map +1 -1
  34. package/package.json +5 -4
@@ -1,11 +1,11 @@
1
1
  import { WINDOW, browserTracingIntegration, startBrowserTracingPageLoadSpan, startBrowserTracingNavigationSpan } from '@sentry/browser';
2
- import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, debug, addNonEnumerableProperty, spanToJSON, getCurrentScope, getClient } from '@sentry/core';
2
+ import { PAGELOAD_SPAN_NAME_FALLBACK, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, hasSpanStreamingEnabled, debug, addNonEnumerableProperty, spanToJSON, getCurrentScope, getClient, 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
7
  import { getActiveRootSpan, setNavigationContext, clearNavigationContext, resolveRouteNameAndSource, transactionNameHasWildcard, initializeRouterUtils } from './utils.js';
8
- import { URL_TEMPLATE } from '@sentry/conventions/attributes';
8
+ import { SENTRY_SEGMENT_NAME_SOURCE, SENTRY_OP, URL_TEMPLATE } from '@sentry/conventions/attributes';
9
9
 
10
10
  let _useEffect;
11
11
  let _useLocation;
@@ -112,12 +112,12 @@ function processResolvedRoutes(resolvedRoutes, parentRoute, currentLocation = nu
112
112
  }
113
113
  const targetSpan = capturedSpan ?? getActiveRootSpan();
114
114
  if (targetSpan) {
115
- const spanJson = spanToJSON(targetSpan);
116
- if (spanJson.timestamp) {
115
+ const { end_timestamp, attributes } = spanToJSON(targetSpan);
116
+ if (end_timestamp) {
117
117
  DEBUG_BUILD && debug.warn("[React Router] Lazy handler resolved after span ended - skipping update");
118
118
  return;
119
119
  }
120
- const spanOp = spanJson.op;
120
+ const spanOp = attributes[SENTRY_OP];
121
121
  let location = currentLocation;
122
122
  if (!location && !capturedSpan) {
123
123
  if (typeof WINDOW !== "undefined") {
@@ -142,12 +142,11 @@ function processResolvedRoutes(resolvedRoutes, parentRoute, currentLocation = nu
142
142
  }
143
143
  }
144
144
  function updateNavigationSpan(activeRootSpan, location, allRoutes2, forceUpdate = false, matchRoutes) {
145
- const spanJson = spanToJSON(activeRootSpan);
146
- const currentName = spanJson.description;
145
+ const { name: currentName, end_timestamp, attributes } = spanToJSON(activeRootSpan);
147
146
  const hasBeenNamed = activeRootSpan?.__sentry_navigation_name_set__;
148
147
  const currentNameHasWildcard = currentName && transactionNameHasWildcard(currentName);
149
148
  const shouldUpdate = !hasBeenNamed || forceUpdate || currentNameHasWildcard;
150
- if (shouldUpdate && !spanJson.timestamp) {
149
+ if (shouldUpdate && !end_timestamp) {
151
150
  const currentBranches = matchRoutes(allRoutes2, location);
152
151
  const [name, source] = resolveRouteNameAndSource(
153
152
  location,
@@ -158,14 +157,16 @@ function updateNavigationSpan(activeRootSpan, location, allRoutes2, forceUpdate
158
157
  _lazyRouteManifest,
159
158
  _enableAsyncRouteHandlers
160
159
  );
161
- const currentSource = spanJson.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
160
+ const currentSource = attributes[SENTRY_SEGMENT_NAME_SOURCE];
162
161
  const isImprovement = name && (!currentName || // No current name - always set
163
162
  !hasBeenNamed && (currentSource !== "route" || source === "route") || // Not finalized - allow unless downgrading route→url
164
163
  currentSource !== "route" && source === "route" || // URL → route upgrade
165
164
  currentSource === "route" && source === "route" && currentNameHasWildcard);
166
165
  if (isImprovement) {
167
- activeRootSpan.updateName(name);
168
- activeRootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
166
+ const client = getClient();
167
+ const isUnparameterizedStreamedNavigation = source !== "route" && !!client && hasSpanStreamingEnabled(client);
168
+ activeRootSpan.updateName(isUnparameterizedStreamedNavigation ? NAVIGATION_SPAN_NAME_FALLBACK : name);
169
+ activeRootSpan.setAttribute(SENTRY_SEGMENT_NAME_SOURCE, source);
169
170
  if (source === "route") {
170
171
  activeRootSpan.setAttribute(URL_TEMPLATE, name);
171
172
  }
@@ -177,14 +178,14 @@ function updateNavigationSpan(activeRootSpan, location, allRoutes2, forceUpdate
177
178
  }
178
179
  function setupRouterSubscription(router, routes, version, basename, activeRootSpan) {
179
180
  let isInitialPageloadComplete = false;
180
- let hasSeenPageloadSpan = !!activeRootSpan && spanToJSON(activeRootSpan).op === "pageload";
181
+ let hasSeenPageloadSpan = !!activeRootSpan && spanToJSON(activeRootSpan).attributes[SENTRY_OP] === "pageload";
181
182
  let hasSeenPopAfterPageload = false;
182
183
  let scheduledNavigationHandler = null;
183
184
  let lastHandledPathname = null;
184
185
  router.subscribe((state) => {
185
186
  if (!isInitialPageloadComplete) {
186
187
  const currentRootSpan = getActiveRootSpan();
187
- const isCurrentlyInPageload = currentRootSpan && spanToJSON(currentRootSpan).op === "pageload";
188
+ const isCurrentlyInPageload = currentRootSpan && spanToJSON(currentRootSpan).attributes[SENTRY_OP] === "pageload";
188
189
  if (isCurrentlyInPageload) {
189
190
  hasSeenPageloadSpan = true;
190
191
  } else if (hasSeenPageloadSpan) {
@@ -370,9 +371,11 @@ function createReactRouterV6CompatibleTracingIntegration(options, version) {
370
371
  const initPathName = WINDOW.location?.pathname;
371
372
  if (instrumentPageLoad && initPathName) {
372
373
  startBrowserTracingPageLoadSpan(client, {
373
- name: initPathName,
374
+ // With span streaming, span names have to be low cardinality. The route is only resolved
375
+ // once the router renders, which updates the span name then.
376
+ name: hasSpanStreamingEnabled(client) ? PAGELOAD_SPAN_NAME_FALLBACK : initPathName,
374
377
  attributes: {
375
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
378
+ [SENTRY_SEGMENT_NAME_SOURCE]: "url",
376
379
  [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "pageload",
377
380
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.pageload.react.reactrouter${version ? `_v${version}` : ""}`
378
381
  }
@@ -460,8 +463,8 @@ function wrapPatchRoutesOnNavigation(opts, isMemoryRouter = false, capturedSpan)
460
463
  }
461
464
  }
462
465
  const spanJson = activeRootSpan ? spanToJSON(activeRootSpan) : void 0;
463
- if (targetPath && activeRootSpan && spanJson && !spanJson.timestamp && // Span hasn't ended yet
464
- spanJson.op === "navigation") {
466
+ if (targetPath && activeRootSpan && spanJson && !spanJson.end_timestamp && // Span hasn't ended yet
467
+ spanJson.attributes[SENTRY_OP] === "navigation") {
465
468
  updateNavigationSpan(
466
469
  activeRootSpan,
467
470
  { pathname: targetPath, search: "", hash: "", state: null, key: "default" },
@@ -486,8 +489,8 @@ function wrapPatchRoutesOnNavigation(opts, isMemoryRouter = false, capturedSpan)
486
489
  }
487
490
  }
488
491
  const spanJson = activeRootSpan ? spanToJSON(activeRootSpan) : void 0;
489
- if (activeRootSpan && spanJson && !spanJson.timestamp && // Span hasn't ended yet
490
- spanJson.op === "navigation") {
492
+ if (activeRootSpan && spanJson && !spanJson.end_timestamp && // Span hasn't ended yet
493
+ spanJson.attributes[SENTRY_OP] === "navigation") {
491
494
  const pathname = targetPath;
492
495
  if (pathname) {
493
496
  updateNavigationSpan(
@@ -516,7 +519,7 @@ function handleNavigation(opts) {
516
519
  return;
517
520
  }
518
521
  const activeRootSpan = getActiveRootSpan();
519
- if (activeRootSpan && spanToJSON(activeRootSpan).op === "pageload" && navigationType === "POP") {
522
+ if (activeRootSpan && spanToJSON(activeRootSpan).attributes[SENTRY_OP] === "pageload" && navigationType === "POP") {
520
523
  return;
521
524
  }
522
525
  if ((navigationType === "PUSH" || navigationType === "POP") && branches) {
@@ -531,7 +534,7 @@ function handleNavigation(opts) {
531
534
  );
532
535
  const locationKey = computeLocationKey(location);
533
536
  const trackedNav = activeNavigationSpans.get(client);
534
- const trackedSpanHasEnded = trackedNav && !trackedNav.isPlaceholder ? !!spanToJSON(trackedNav.span).timestamp : false;
537
+ const trackedSpanHasEnded = trackedNav && !trackedNav.isPlaceholder ? !!spanToJSON(trackedNav.span).end_timestamp : false;
535
538
  const { skip, shouldUpdate } = shouldSkipNavigation(trackedNav, locationKey, name, trackedSpanHasEnded);
536
539
  if (skip) {
537
540
  if (shouldUpdate && trackedNav) {
@@ -542,8 +545,9 @@ function handleNavigation(opts) {
542
545
  `[Tracing] Updated placeholder navigation name from "${oldName}" to "${name}" (will apply to real span)`
543
546
  );
544
547
  } else {
545
- trackedNav.span.updateName(name);
546
- trackedNav.span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
548
+ const isUnparameterizedStreamedNavigation = source !== "route" && hasSpanStreamingEnabled(client);
549
+ trackedNav.span.updateName(isUnparameterizedStreamedNavigation ? NAVIGATION_SPAN_NAME_FALLBACK : name);
550
+ trackedNav.span.setAttribute(SENTRY_SEGMENT_NAME_SOURCE, source);
547
551
  if (source === "route") {
548
552
  trackedNav.span.setAttribute(URL_TEMPLATE, name);
549
553
  }
@@ -569,10 +573,11 @@ function handleNavigation(opts) {
569
573
  let navigationSpan;
570
574
  try {
571
575
  navigationSpan = startBrowserTracingNavigationSpan(client, {
572
- name: placeholderEntry.routeName,
573
- // Use placeholder's routeName in case it was updated
576
+ // Use placeholder's routeName in case it was updated. With span streaming, span names have to
577
+ // be low cardinality, so we can't fall back to the URL.
578
+ name: source === "route" || !hasSpanStreamingEnabled(client) ? placeholderEntry.routeName : NAVIGATION_SPAN_NAME_FALLBACK,
574
579
  attributes: {
575
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
580
+ [SENTRY_SEGMENT_NAME_SOURCE]: source,
576
581
  [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
577
582
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.navigation.react.reactrouter${version ? `_v${version}` : ""}`,
578
583
  ...source === "route" && { [URL_TEMPLATE]: placeholderEntry.routeName }
@@ -647,8 +652,10 @@ function updatePageloadTransaction({
647
652
  );
648
653
  getCurrentScope().setTransactionName(name || "/");
649
654
  if (activeRootSpan) {
650
- activeRootSpan.updateName(name);
651
- activeRootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
655
+ const client = getClient();
656
+ const isUnparameterizedStreamedPageload = source !== "route" && !!client && hasSpanStreamingEnabled(client);
657
+ activeRootSpan.updateName(isUnparameterizedStreamedPageload ? PAGELOAD_SPAN_NAME_FALLBACK : name);
658
+ activeRootSpan.setAttribute(SENTRY_SEGMENT_NAME_SOURCE, source);
652
659
  if (source === "route") {
653
660
  activeRootSpan.setAttribute(URL_TEMPLATE, name);
654
661
  }
@@ -676,7 +683,7 @@ function shouldUpdateWildcardSpanName(currentName, currentSource, newName, newSo
676
683
  }
677
684
  function tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes, basename, spanType, allRoutes2) {
678
685
  try {
679
- const currentSource = spanJson.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
686
+ const currentSource = spanJson.attributes[SENTRY_SEGMENT_NAME_SOURCE];
680
687
  if (currentSource === "route" && currentName && !transactionNameHasWildcard(currentName)) {
681
688
  return;
682
689
  }
@@ -696,10 +703,13 @@ function tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, route
696
703
  _enableAsyncRouteHandlers
697
704
  );
698
705
  const isImprovement = shouldUpdateWildcardSpanName(currentName, currentSource, name, source, true);
699
- const spanNotEnded = spanType === "pageload" || !spanJson.timestamp;
706
+ const spanNotEnded = spanType === "pageload" || !spanJson.end_timestamp;
700
707
  if (isImprovement && spanNotEnded) {
701
- span.updateName(name);
702
- span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
708
+ const client = getClient();
709
+ const isUnparameterizedStreamedSpan = source !== "route" && !!client && hasSpanStreamingEnabled(client);
710
+ const fallbackName = spanType === "pageload" ? PAGELOAD_SPAN_NAME_FALLBACK : NAVIGATION_SPAN_NAME_FALLBACK;
711
+ span.updateName(isUnparameterizedStreamedSpan ? fallbackName : name);
712
+ span.setAttribute(SENTRY_SEGMENT_NAME_SOURCE, source);
703
713
  if (source === "route") {
704
714
  span.setAttribute(URL_TEMPLATE, name);
705
715
  }
@@ -723,8 +733,8 @@ function patchSpanEnd(span, location, routes, basename, spanType) {
723
733
  endCalled = true;
724
734
  const endTimestamp = args.length > 0 ? args[0] : Date.now() / 1e3;
725
735
  const spanJson = spanToJSON(span);
726
- const currentName = spanJson.description;
727
- const currentSource = spanJson.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
736
+ const currentName = spanJson.name;
737
+ const currentSource = spanJson.attributes[SENTRY_SEGMENT_NAME_SOURCE];
728
738
  const cleanupNavigationSpan = () => {
729
739
  const client = getClient();
730
740
  if (client && spanType === "navigation") {
@@ -759,7 +769,7 @@ function patchSpanEnd(span, location, routes, basename, spanType) {
759
769
  tryUpdateSpanNameBeforeEnd(
760
770
  span,
761
771
  updatedSpanJson,
762
- updatedSpanJson.description,
772
+ updatedSpanJson.name,
763
773
  location,
764
774
  routes,
765
775
  basename,