Skip to content

fix(compose): Prevent dangling spans in SentryTraced + tag composition outcome - #6049

Merged
0xadam-brown merged 2 commits into
mainfrom
fix/sentry-traced-dangling-spans
Sep 3, 2026
Merged

fix(compose): Prevent dangling spans in SentryTraced + tag composition outcome#6049
0xadam-brown merged 2 commits into
mainfrom
fix/sentry-traced-dangling-spans

Conversation

@0xadam-brown

@0xadam-brown 0xadam-brown commented Sep 3, 2026

Copy link
Copy Markdown
Member

📜 Description

PR repairs a few defects in the implementation of SentryTraced while aiming to maintain parity with the previous approach. In particular it:

  1. Prevents dangling composition spans in cases where the Compose runtime abandons the composition. (We now delay creating the span until a SideEffect executes.)

  2. Prevents dangling render spans in cases where drawContent() throws and the host app recovers. (Similarly, we delay creating the span until drawContent() completes successfully.)

💡 Motivation and Context

Dangling spans remain attached to their parent transaction and can delay transaction capture if waitForChildren is enabled. They're also confusing in the Sentry dashboard because they look like poor performing compositions, when in fact they will have simply been abandoned in the ordinary course by the Compose runtime.

Spans before vs after

I had my clanker exercise SentryTraced composables in our sample app to test span durations before this change vs after. Expand below to see the results (tl;dr they're comparable, which is what we want).

Details
Flow Baseline Latest rerun
Stock MainActivity -> Integrations -> Compose 11 ui.compose + 11 ui.render child spans 21 ui.compose + 21 ui.render child spans
Extra Integrations spans in stock flow No Yes
composition.result tag No No
Child ui.render origin manual manual
ComposeActivity-first child span set 7 ui.compose + 7 ui.render 7 ui.compose + 7 ui.render

Note: We're likely seeing more spans after this PR (21 vs 11) because of a race that's always been present between when the root transaction becomes active vs when we start the composition span. We now start later, which means the transaction has more time to set itself up, and therefore fewer spans are lost. I plan to tackle this problem fully with the introduction of LocalSentrySpan in a subsequent PR.

Span description Baseline (ms) Latest rerun (ms) Delta (ms)
Jetpack Compose Initial Composition 106.549 113.869 +7.320
navhost 10.408 16.849 +6.441
buttons_page 43.769 28.652 -15.117
button_nav_github 24.341 10.637 -13.704
button_nav_github_args 1.702 0.755 -0.947
button_crash 2.749 0.643 -2.106
button_dialog (first) 2.671 0.770 -1.901
button_dialog (second) 8.746 14.314 +5.568
Span description Baseline (ms) Latest rerun (ms) Delta (ms)
Jetpack Compose Initial Render 7.311 10.561 +3.250
navhost 7.311 10.561 +3.250
buttons_page 7.006 10.377 +3.371
button_nav_github 3.287 2.813 -0.474
button_nav_github_args 0.535 1.163 +0.628
button_crash 0.245 0.761 +0.516
button_dialog (first) 0.251 0.937 +0.686
button_dialog (second) 1.902 2.842 +0.940

💚 How did you test it?

Unit tests and manual tests.

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.

🔮 Next steps

Two more SentryTraced related PRs:

  1. Behavior changes: Only report a composition span for the first successful composition + include origin info with the render span like we do with the composition span.
  2. Fix the currently broken CompositionLocals that lead to the possibility of a stale parent transaction via a new LocalSentrySpan CompositionLocal.

@sentry

sentry Bot commented Sep 3, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.55.0 (1) release

⚙️ sentry-android Build Distribution Settings

@0xadam-brown
0xadam-brown force-pushed the fix/sentry-traced-dangling-spans branch from d698dce to 3e66b34 Compare September 3, 2026 03:49
Comment thread sentry-compose/src/androidMain/kotlin/io/sentry/compose/SentryComposeTracing.kt Outdated
@0xadam-brown
0xadam-brown marked this pull request as ready for review September 3, 2026 04:02
Comment thread sentry-compose/src/androidMain/kotlin/io/sentry/compose/SentryComposeTracing.kt Outdated
@0xadam-brown
0xadam-brown marked this pull request as draft September 3, 2026 05:15
Commit repairs a few defects in the implementation of SentryTraced while aiming to maintain parity with the previous approach. In particular it:

- Prevents dangling composition spans in cases where the Compose runtime abandons the composition. (We now delay creating the span until a SideEffect executes.)

- Prevents dangling render spans in cases where drawContent() throws and the host app recovers. (Similarly, we delay creating the span until drawContent() completes successfully.)
@0xadam-brown
0xadam-brown force-pushed the fix/sentry-traced-dangling-spans branch from 3e66b34 to a85abfe Compare September 3, 2026 07:02
@0xadam-brown
0xadam-brown marked this pull request as ready for review September 3, 2026 07:27
@0xadam-brown
0xadam-brown marked this pull request as draft September 3, 2026 08:16
@0xadam-brown

Copy link
Copy Markdown
Member Author

Sorry for the churn. Need to incorporate a few additional changes. Back shortly...

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! I'm not an expert in compose so feel free to ignore these comments

Comment thread sentry-compose/src/androidMain/kotlin/io/sentry/compose/SentryComposeTracing.kt Outdated
Comment thread sentry-compose/src/androidMain/kotlin/io/sentry/compose/SentryComposeTracing.kt Outdated
@0xadam-brown

Copy link
Copy Markdown
Member Author

Ready for review again. No changes from before – the other work was substantial enough that I'll create a separate PR for it.

@0xadam-brown
0xadam-brown marked this pull request as ready for review September 3, 2026 09:03
@0xadam-brown
0xadam-brown enabled auto-merge (squash) September 3, 2026 11:30
@0xadam-brown
0xadam-brown merged commit cdb89fd into main Sep 3, 2026
70 of 71 checks passed
@0xadam-brown
0xadam-brown deleted the fix/sentry-traced-dangling-spans branch September 3, 2026 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants