You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(tracing): Wrap Expo Router push, replace, navigate, back, dismiss in addition to prefetch (#6221)
* Wrap push, replace, navigate, back, dismiss in addition to prefetch
* fix(tracing): Guard Expo Router navigation breadcrumbs and spans behind sendDefaultPii
Expo Router `push`/`replace`/`navigate`/`back`/`dismiss` (and `prefetch`)
wrappers previously emitted the raw `href` and route `params` on both
the navigation breadcrumb and span attributes regardless of the client
options. Dynamic segments like `/users/123` and parameter values such
as `{ id: '123' }` can carry user identifiers and other PII, so the
existing `reactnavigation.ts` integration already gates them behind
`sendDefaultPii`. The new Expo Router wrappers should follow the same
contract.
This change:
- Reads `sendDefaultPii` from the client options and only attaches
`href` (raw string or stringified object form) and `params` to the
breadcrumb `data` and span attributes when it is enabled.
- Keeps the non-PII fields — `method`, `pathname` (route template),
and `route.name` — unconditional so navigations remain visible and
groupable in Sentry without leaking user data.
- Applies the same guard to the `prefetch` span's `route.href`
attribute, which was newly added in this PR.
- Adds dedicated `sendDefaultPii` test cases and updates the existing
default-off assertions for all wrapped methods.
- Adds a changelog entry for #6221.
* Fixes
* Changelog fix
* test(tracing): Cover pendingExpoRouterNavigation hand-off in reactNavigationIntegration
The Expo Router wrapper sets a pending navigation value that the
React Navigation idle-span listener is supposed to consume and apply
to the resulting transaction as the `navigation.method` attribute.
Previously only the setter side (in expoRouter.test.ts) was tested;
the consumer side had no coverage, so a regression in
reactnavigation.ts would have gone undetected.
Add three integration-level tests against the live
reactNavigationIntegration:
- the next navigation transaction is tagged with `navigation.method`
matching the pending Expo Router call
- the pending value is consumed exactly once and does not leak into
the following navigation
- no `navigation.method` attribute is set when nothing is pending
Surfaced by Warden review (4UA-DHD).
* fix(tracing): Drain pendingExpoRouterNavigation even when the idle-span listener short-circuits
`startIdleNavigationSpan` has several early-return paths (dispatched
noops, PRELOAD with prefetch tracking, SET_PARAMS, drawer actions, and
`useDispatchedActionData` calls without a route name in the payload).
Previously `consumePendingExpoRouterNavigation()` lived after those
returns, so a wrapped Expo Router call that ended up taking one of the
short-circuit paths left its pending value in the module-level slot.
The next, unrelated navigation then incorrectly inherited the wrong
`navigation.method` attribute.
Move the `consumePendingExpoRouterNavigation()` call to the very top of
the listener so the value is always drained on the listener invocation
triggered by the wrapper. Apply it to the span only if we actually
create one.
Add a regression test covering the dispatched-action-without-payload
early-return path; the test fails on the previous code and passes with
the fix.
Surfaced by sentry-bot and cursor-bot reviews.
* fix(tracing): Use spec-compliant `auto.navigation.expo_router` origin
Per the Sentry trace-origin spec
(https://develop.sentry.dev/sdk/telemetry/traces/trace-origin/), the
`sentry.origin` value uses the format `type.category.integration-name`,
where `category` is a span operation category such as `navigation`.
The new origin for wrapped Expo Router push/replace/navigate/back/dismiss
calls was `auto.expo_router.navigation`, which swaps the category and
integration name. Align it with the existing
`auto.navigation.react_navigation` and
`auto.navigation.react_native_navigation` constants so server-side
filtering and downstream tools recognize these as navigation spans.
The pre-existing `auto.expo_router.prefetch` origin has the same
inverted ordering but is left unchanged here \u2014 it is already shipped
and changing it would break consumers that filter by it.
Surfaced by cursor-bot review.
* docs(changelog): Note Expo Router prefetch PII-gating behavior change
The PR also tightened PII handling for the pre-existing `prefetch`
instrumentation: when `sendDefaultPii` is off (the default),
`route.href` is dropped and concrete pathnames derived from string
hrefs (e.g. `/users/42`) are replaced with `'unknown'` for
`route.name`. Templated object hrefs are unaffected.
Document this so users with dashboards or alerts filtering on
prefetch `route.name`/`route.href` notice the change.
Surfaced by cursor-bot review.
* refactor(tracing): Drop unused fields from PendingExpoRouterNavigation
The consumer in `reactnavigation.ts` only reads `.method`; the `href`,
`pathname`, and `params` fields were populated by `wrapExpoRouter` but
never used. Remove them from the interface and the setter call so the
type accurately reflects what the hand-off actually carries.
Surfaced by code review (antonis).
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,6 +12,8 @@
12
12
13
13
- Add memory, CPU, and frame measurements to Android profiling ([#6250](https://github.com/getsentry/sentry-react-native/pull/6250))
14
14
- Add `enableAutoConsoleLogs` option to opt out of automatic `console.*` capture while keeping `enableLogs: true` for manual `Sentry.logger.*` calls ([#6235](https://github.com/getsentry/sentry-react-native/pull/6235))
15
+
- Instrument Expo Router `push`, `replace`, `navigate`, `back`, and `dismiss` (in addition to `prefetch`) with breadcrumbs and spans, and tag the resulting idle navigation span with the initiating `navigation.method` ([#6221](https://github.com/getsentry/sentry-react-native/pull/6221))
16
+
- Note: Expo Router span/breadcrumb attributes that may contain user identifiers (`route.href`, `route.params`, and concrete pathnames derived from string hrefs such as `/users/42`) are now gated behind `sendDefaultPii`. When `sendDefaultPii` is off (the default), prefetch spans for string hrefs use `route.name: 'unknown'` and omit `route.href`. Templated object hrefs (e.g. `{ pathname: '/users/[id]' }`) are unaffected.
15
17
- Warn when Gradle resolves `sentry-android` to a version incompatible with the SDK ([#6238](https://github.com/getsentry/sentry-react-native/pull/6238))
// src/js/feedback/integration.ts:21:5 - (ae-forgotten-export) The symbol "ScreenshotButtonProps" needs to be exported by the entry point index.d.ts
857
858
// src/js/feedback/integration.ts:23:5 - (ae-forgotten-export) The symbol "FeedbackFormTheme" needs to be exported by the entry point index.d.ts
858
859
// src/js/tracing/reactnativetracing.ts:90:3 - (ae-forgotten-export) The symbol "ReactNativeTracingState" needs to be exported by the entry point index.d.ts
859
-
// src/js/tracing/reactnavigation.ts:219:3 - (ae-forgotten-export) The symbol "RouteOverrideProvider" needs to be exported by the entry point index.d.ts
860
+
// src/js/tracing/reactnavigation.ts:220:3 - (ae-forgotten-export) The symbol "RouteOverrideProvider" needs to be exported by the entry point index.d.ts
860
861
861
862
// (No @packageDocumentation comment for this package)
0 commit comments