Skip to content

Nav3 SentryTraced spans attach to another root’s navigation transaction #6368

Open

Description

@0xadam-brown

Description

When multiple Nav3 roots are hosted by different Activities or Fragments, SentryTraced can attach a route's ui.compose and ui.render spans to another root's navigation transaction. This produces a trace whose transaction name and child route names disagree.

Reproduced with the Android sample app on fix/nav3-view-pager-2 (sample build from c1113ebedb; a later amend changed only tests), version 8.61.1, on an API 37 emulator. The sample's Recent transactions sheet reads the finished SentryTransaction from beforeSendTransaction, so the mismatch is in the transaction sent by the SDK.

Steps to reproduce

Multi-Activity

  1. In the Android sample, open Nav3 Activity with the default setup, then select Multi-Activity.
  2. Open Products Activity → Open Product 42.
  3. Tap Push Confirmation in 5 s, then immediately tap Go to Checkout to open Checkout Activity.
  4. After the delayed route is pushed in the background Products Activity, leave Checkout and inspect Recent transactions.

The tagged controls are nav3_tab_multi_activity, nav3_multi_activity_open_products, nav3_product_list_open_product_42, nav3_product_detail_delayed_confirmation, and nav3_product_detail_go_to_checkout.

Multi-Fragment / ViewPager2

  1. In the same sample, select Multi-Fragment → Open fragments Activity → Pager.
  2. Move from Page 0 to Page 1 and Page 2. The neighboring Fragment pages are preloaded at STARTED (offscreenPageLimit = 1).
  3. Inspect the finished Page 0 /ProductList transaction in Recent transactions.

The tagged controls are nav3_tab_multi_fragment, nav3_multi_fragment_open_fragments, nav3_multi_fragment_open_pager, and nav3_multi_fragment_page_0 through _2.

Expected

A SentryTraced route's composition and render spans are children of that route's own navigation transaction. If its root does not currently have a transaction, its spans should not be attached to another root's transaction.

Actual

  • The Checkout Activity's /Checkout transaction contains ui.compose - Nav3 /Confirmation from the background Products Activity. Captured trace.
  • A Page 0 /ProductList transaction contains ui.compose and ui.render spans for Page 1 /Checkout and Page 2 /Confirmation. Captured trace.

The sample's test.navigation.route_activation spans also attach to the wrong transaction in these runs. Those spans come from sample instrumentation; the ui.compose and ui.render spans demonstrate the SDK issue.

Likely cause

SentryTraced obtains its owner from LocalSentrySpan.current.orBootstrapCurrentTransaction() (sentry-compose/.../SentryComposeTracing.kt). The Nav3 sample does not provide a per-entry LocalSentrySpan, so the fallback reads whichever transaction is bound to the shared scope at composition time. A background Activity or preloaded Fragment can compose while another root owns that scope transaction. The Nav3 lease limits which root publishes navigation state but does not bind SentryTraced spans to their entry.

A possible fix is for each Nav3 entry to provide its own parent span to SentryTraced, with a no-op owner when the entry has no transaction. The exact API and preview-span policy need design review.

Related

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions