Problem Statement
Apps with bottom tabs, drawer navigation, or similar patterns often maintain multiple independent backstacks – one per top-level destination – so that users can switch tabs without losing their place. Nav3 doesn't provide a built-in multi-back-stack API; instead, apps own multiple NavBackStack instances and merge their entries before passing them to NavDisplay (see the multiplestacks recipe).
The Stage 1 integration (#5000) and multipane support (#5649) handle a single SnapshotStateList<T> backstack. When an app uses multiple stacks, the SDK needs to understand which stack is active and scope its telemetry accordingly.
Solution Brainstorm
- Stack identification. Introduce a
stack_id concept so breadcrumbs, transactions, and crash context can group navigations per stack. This could be a user-supplied label per stack (e.g. the tab route key's name), or inferred from the NavBackStack identity.
- API surface. Provide a way to register multiple backstacks with a shared
SentryNavStateHolder, or create per-stack holders that coordinate. The app tells us which stack is currently active (likely by passing the active topLevelRoute or equivalent).
scope.screen – set to the active stack's top route. When the user switches tabs, this triggers a navigation breadcrumb and updates scope.screen to the new stack's current top.
- Breadcrumbs – capture both intra-stack navigation (push/pop within a tab) and inter-stack switches (tab change). Include
stack_id in breadcrumb data so the two can be distinguished. A tab switch breadcrumb might look like { from: "/settings/profile", to: "/home/feed", stack_id: "home" }.
- Transactions – when the user switches to a stack whose top entry hasn't changed, should we start a new transaction? Probably not – the screen was already loaded. Only start a transaction on an actual new destination within the stack.
- Crash context (
contexts.navigation) – include all stacks (not just the active one), capped by maxBackstackSize total across stacks. Mark which stack is active.
Open questions:
- Should
contexts.navigation.backstack flatten all stacks into one list, or nest them by stack_id?
- How do multistack and multipane compose? A tablet app might have bottom tabs (multistack) where one tab shows a list-detail layout (multipane). The primary pane logic from Stage 2 should still apply within the active stack.
- Should tab switches reuse the existing
"navigation" breadcrumb category or get a distinct one (e.g. "stack_switch")?
- Do we want to revisit Nav2 simplifications alongside this (nested nav graphs, dialog/bottom-sheet transaction behavior)?
Existing Nav2 support
Nav2 supports multiple backstacks natively via NavController.navigate() with saveState = true / restoreState = true, commonly used with NavigationBar or BottomNavigation. However, the current Nav2 integration does not distinguish between stacks – it sees a flat stream of destination changes on a single NavController and treats every destination change identically. There is no stack_id, no differentiation between intra-tab navigation and tab switches, and no per-stack grouping in crash context. A tab switch looks the same as a forward navigation in telemetry.
Problem Statement
Apps with bottom tabs, drawer navigation, or similar patterns often maintain multiple independent backstacks – one per top-level destination – so that users can switch tabs without losing their place. Nav3 doesn't provide a built-in multi-back-stack API; instead, apps own multiple
NavBackStackinstances and merge their entries before passing them toNavDisplay(see themultiplestacksrecipe).The Stage 1 integration (#5000) and multipane support (#5649) handle a single
SnapshotStateList<T>backstack. When an app uses multiple stacks, the SDK needs to understand which stack is active and scope its telemetry accordingly.Solution Brainstorm
stack_idconcept so breadcrumbs, transactions, and crash context can group navigations per stack. This could be a user-supplied label per stack (e.g. the tab route key's name), or inferred from theNavBackStackidentity.SentryNavStateHolder, or create per-stack holders that coordinate. The app tells us which stack is currently active (likely by passing the activetopLevelRouteor equivalent).scope.screen– set to the active stack's top route. When the user switches tabs, this triggers a navigation breadcrumb and updatesscope.screento the new stack's current top.stack_idin breadcrumb data so the two can be distinguished. A tab switch breadcrumb might look like{ from: "/settings/profile", to: "/home/feed", stack_id: "home" }.contexts.navigation) – include all stacks (not just the active one), capped bymaxBackstackSizetotal across stacks. Mark which stack is active.Open questions:
contexts.navigation.backstackflatten all stacks into one list, or nest them bystack_id?"navigation"breadcrumb category or get a distinct one (e.g."stack_switch")?Existing Nav2 support
Nav2 supports multiple backstacks natively via
NavController.navigate()withsaveState = true/restoreState = true, commonly used withNavigationBarorBottomNavigation. However, the current Nav2 integration does not distinguish between stacks – it sees a flat stream of destination changes on a singleNavControllerand treats every destination change identically. There is nostack_id, no differentiation between intra-tab navigation and tab switches, and no per-stack grouping in crash context. A tab switch looks the same as a forward navigation in telemetry.