Skip to content

Commit 084c3cb

Browse files
0xadam-brownclaude
andauthored
fix(sample): Drop Nav3 Activity ui.load transactions when the toggle is off (#6401)
The sample cancelled the Activity's ui.load transaction through the scope. When another transaction was already bound, such as the previous Activity's nav transaction, the SDK didn't bind ui.load, so the cancel missed and the transaction was still sent, often waiting the full deadline with the Activity's spans. Keep cancelling a bound ui.load transaction so it doesn't block the first nav transaction, and also drop Nav3 sample Activities' ui.load transactions in an event processor when the Activity was created with the toggle off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 3eef688 commit 084c3cb

4 files changed

Lines changed: 57 additions & 14 deletions

File tree

‎sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/nav3/Nav3Activity.kt‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,10 @@ class Nav3Activity : ComponentActivity() {
9292
configuration.applyToCurrentOptions()
9393
showActivityUiLoadTransactionDelayMessage = configuration.hasOnlyActivityUiLoadTransactions
9494

95-
if (!configuration.enableActivityUiLoadTransaction) {
96-
// Cancel the already-started Activity transaction before Compose installs SentryNavEffect,
97-
// otherwise the initial /Landing route transaction gets preempted by the lingering ui.load.
98-
cancelCurrentActivityUiLoadTransaction()
99-
}
95+
// When the toggle is off, cancel the already-started Activity transaction before Compose
96+
// installs SentryNavEffect, otherwise the lingering ui.load preempts the initial /Landing route
97+
// transaction.
98+
applyActivityUiLoadTransactionSetting(this, configuration.enableActivityUiLoadTransaction)
10099

101100
NavigationTransactionHistory.install()
102101

‎sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/nav3/Nav3MultiActivity.kt‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,7 @@ class Nav3ProductsActivity : ComponentActivity() {
8989
super.onCreate(savedInstanceState)
9090
val configuration = (intent.extras ?: Bundle()).nav3SampleConfiguration()
9191
NavigationTransactionHistory.install()
92-
if (!configuration.enableActivityUiLoadTransaction) {
93-
cancelCurrentActivityUiLoadTransaction()
94-
}
92+
applyActivityUiLoadTransactionSetting(this, configuration.enableActivityUiLoadTransaction)
9593
setContent {
9694
val stack = rememberSaveableNav3BackStack(Nav3Route.ProductList)
9795
SideEffect {
@@ -174,9 +172,7 @@ open class Nav3CheckoutActivity : ComponentActivity() {
174172
val crashOnFirstComposition =
175173
savedInstanceState == null && intent.getBooleanExtra(EXTRA_CRASH_ON_FIRST_COMPOSITION, false)
176174
NavigationTransactionHistory.install()
177-
if (!configuration.enableActivityUiLoadTransaction) {
178-
cancelCurrentActivityUiLoadTransaction()
179-
}
175+
applyActivityUiLoadTransactionSetting(this, configuration.enableActivityUiLoadTransaction)
180176
setContent {
181177
Nav3SampleTheme {
182178
if (showAsSheet) {

‎sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/nav3/Nav3MultiFragment.kt‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,7 @@ class Nav3FragmentsActivity : FragmentActivity() {
7676
override fun onCreate(savedInstanceState: Bundle?) {
7777
super.onCreate(savedInstanceState)
7878
NavigationTransactionHistory.install()
79-
if (!configuration.enableActivityUiLoadTransaction) {
80-
cancelCurrentActivityUiLoadTransaction()
81-
}
79+
applyActivityUiLoadTransactionSetting(this, configuration.enableActivityUiLoadTransaction)
8280

8381
val controls =
8482
ComposeView(this).apply {

‎sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/nav3/Nav3SampleTracing.kt‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
package io.sentry.samples.android.navigation.nav3
22

3+
import android.app.Activity
4+
import io.sentry.EventProcessor
5+
import io.sentry.Hint
36
import io.sentry.Sentry
47
import io.sentry.SpanStatus
58
import io.sentry.protocol.SentryTransaction
9+
import java.util.Collections
10+
import java.util.concurrent.ConcurrentHashMap
611
import kotlin.coroutines.resume
712
import kotlinx.coroutines.suspendCancellableCoroutine
813

@@ -21,6 +26,51 @@ internal fun SentryTransaction.navigationSampleScenarioLabel(): String =
2126
?: getTag(NAV3_SCENARIO_TAG)
2227
?: UNKNOWN_NAVIGATION_SCENARIO_LABEL
2328

29+
/**
30+
* Applies the sample's "Activity ui.load transaction" toggle to [activity].
31+
*
32+
* Call from `onCreate` after `super.onCreate`, once the SDK has started the Activity's ui.load
33+
* transaction. When [enabled] is false, the transaction is cancelled if it's bound to the scope.
34+
* It's also dropped before sending, because the SDK doesn't bind it when another transaction (such
35+
* as the previous Activity's nav transaction) is already bound, and the sample can't reach an
36+
* unbound ui.load transaction to cancel it.
37+
*/
38+
internal fun applyActivityUiLoadTransactionSetting(activity: Activity, enabled: Boolean) {
39+
// Matches the transaction name ActivityLifecycleIntegration uses.
40+
val activityName = activity.javaClass.simpleName
41+
if (enabled) {
42+
SuppressedActivityUiLoadTransactions.activityNames.remove(activityName)
43+
return
44+
}
45+
SuppressedActivityUiLoadTransactions.install()
46+
SuppressedActivityUiLoadTransactions.activityNames.add(activityName)
47+
cancelCurrentActivityUiLoadTransaction()
48+
}
49+
50+
/** Drops ui.load transactions for sample Activities created with the ui.load toggle off. */
51+
private object SuppressedActivityUiLoadTransactions : EventProcessor {
52+
val activityNames: MutableSet<String> =
53+
Collections.newSetFromMap(ConcurrentHashMap<String, Boolean>())
54+
55+
@Volatile private var installed = false
56+
57+
fun install() {
58+
if (installed) return
59+
synchronized(this) {
60+
if (installed) return
61+
Sentry.getCurrentScopes().options.addEventProcessor(this)
62+
installed = true
63+
}
64+
}
65+
66+
override fun process(transaction: SentryTransaction, hint: Hint): SentryTransaction? {
67+
val isSuppressed =
68+
transaction.contexts.trace?.operation == ACTIVITY_UI_LOAD_OP &&
69+
transaction.transaction in activityNames
70+
return if (isSuppressed) null else transaction
71+
}
72+
}
73+
2474
internal fun cancelCurrentActivityUiLoadTransaction() {
2575
Sentry.configureScope { scope ->
2676
scope.withTransaction { transaction ->

0 commit comments

Comments
 (0)