Skip to content

Commit a8aeb7e

Browse files
committed
fix(compose): Honor ignored origins in SentryTraced spans
Fix a bug where we set span origins for SentryTraced after their creation via the span context, resulting in our ignore-span-origins logic not being able to see them and spans being produced when they should have been ignored / suppressed. What was happening? SentryTracer checks `ignoredSpanOrigins` during span creation, before the returned span can be mutated: ```java if (SpanUtils.isIgnored(scopes.getOptions().getIgnoredSpanOrigins(), spanOptions.getOrigin())) { return NoOpSpan.getInstance(); } ``` That check reads SpanOptions.origin, not the SpanContext.origin we were setting after creation. So if a host app did this... ```kotlin options.setIgnoredSpanOrigins(listOf("auto.ui.jetpack_compose")) ``` ...it would no-op and the Compose spans were created nonetheless. The issue affected both levels of the SentryTraced span hierarchy (ie, both parent spans and child spans).
1 parent c0b7806 commit a8aeb7e

3 files changed

Lines changed: 46 additions & 12 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
### Fixes
66

7-
`SentryTraced` now checks for its owning transaction dynamically rather than once per app process. The latter caused `SentryTraced` spans to be dropped process-wide once the original transaction finished ([#6057](https://github.com/getsentry/sentry-java/pull/6057))
7+
- Update `SentryTraced` so that it now honors `options.setIgnoredSpanOrigins` ([#6058](https://github.com/getsentry/sentry-java/pull/6058))
8+
- `SentryTraced` now checks for its owning transaction dynamically rather than once per app process. The latter caused `SentryTraced` spans to be dropped process-wide once the original transaction finished ([#6057](https://github.com/getsentry/sentry-java/pull/6057))
89

910
## 8.55.0
1011

‎sentry-compose/src/androidMain/kotlin/io/sentry/compose/SentryComposeTracing.kt‎

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,15 @@ private fun recordCompositionSpan(
117117
) {
118118
val parentSpan = ParentSpans.getOrCreateCompositionSpan(ownerSpan, startTimestamp) ?: return
119119

120-
parentSpan.startChild(OP_COMPOSITION_CHILD, tag, startTimestamp).apply {
121-
spanContext.origin = OP_TRACE_ORIGIN
122-
finish(null, endTimestamp)
123-
}
120+
parentSpan
121+
.startChild(
122+
OP_COMPOSITION_CHILD,
123+
tag,
124+
startTimestamp,
125+
Instrumenter.SENTRY,
126+
SpanOptions().apply { origin = OP_TRACE_ORIGIN },
127+
)
128+
.run { finish(null, endTimestamp) }
124129
}
125130

126131
private fun recordRenderSpan(
@@ -131,10 +136,15 @@ private fun recordRenderSpan(
131136
) {
132137
val parentSpan = ParentSpans.getOrCreateRenderSpan(ownerSpan, startTimestamp) ?: return
133138

134-
parentSpan.startChild(OP_RENDER_CHILD, tag, startTimestamp).apply {
135-
spanContext.origin = OP_TRACE_ORIGIN
136-
finish(null, endTimestamp)
137-
}
139+
parentSpan
140+
.startChild(
141+
OP_RENDER_CHILD,
142+
tag,
143+
startTimestamp,
144+
Instrumenter.SENTRY,
145+
SpanOptions().apply { origin = OP_TRACE_ORIGIN },
146+
)
147+
.run { finish(null, endTimestamp) }
138148
}
139149

140150
/**
@@ -220,6 +230,7 @@ private class ParentSpans {
220230
startTimestamp,
221231
Instrumenter.SENTRY,
222232
SpanOptions().apply {
233+
origin = OP_TRACE_ORIGIN
223234
isTrimStart = true
224235
isTrimEnd = true
225236
isIdle = true
@@ -229,8 +240,6 @@ private class ParentSpans {
229240
if (parentSpan.dropsChildSpans) {
230241
return null
231242
}
232-
233-
parentSpan.spanContext.origin = OP_TRACE_ORIGIN
234243
setCached(WeakReference(parentSpan))
235244
return parentSpan
236245
}

‎sentry-compose/src/androidUnitTest/kotlin/io/sentry/compose/SentryTracedTest.kt‎

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,26 @@ class SentryTracedTest {
128128
assertThat(tx.countSpans(OP_RENDER)).isEqualTo(0)
129129
}
130130

131+
@Test
132+
fun `does not create spans when compose origin is ignored`() {
133+
val tx =
134+
initSentryAndStartTransaction("tx") { options ->
135+
options.setIgnoredSpanOrigins(listOf(OP_TRACE_ORIGIN))
136+
}
137+
138+
rule.setContent {
139+
SentryTraced(tag = "product_info") { Box(Modifier.size(1.dp).testTag("content")) }
140+
}
141+
rule.waitForIdle()
142+
drawContent()
143+
144+
rule.onNodeWithTag("content").assertExists()
145+
assertThat(tx.countSpans(OP_PARENT_COMPOSITION)).isEqualTo(0)
146+
assertThat(tx.countSpans(OP_COMPOSE)).isEqualTo(0)
147+
assertThat(tx.countSpans(OP_PARENT_RENDER)).isEqualTo(0)
148+
assertThat(tx.countSpans(OP_RENDER)).isEqualTo(0)
149+
}
150+
131151
@Test
132152
fun `sibling traced composables with the same owner share the composition parent`() {
133153
val tx = initSentryAndStartTransaction("tx")
@@ -381,13 +401,17 @@ class SentryTracedTest {
381401
assertThat(renderingTx.countSpans(OP_RENDER)).isEqualTo(0)
382402
}
383403

384-
private fun initSentryAndStartTransaction(name: String): ITransaction {
404+
private fun initSentryAndStartTransaction(
405+
name: String,
406+
configureOptions: (SentryOptions) -> Unit = {},
407+
): ITransaction {
385408
lateinit var tx: ITransaction
386409
rule.runOnUiThread {
387410
Sentry.init(
388411
{ options: SentryOptions ->
389412
options.dsn = "https://key@sentry.io/proj"
390413
options.tracesSampleRate = 1.0
414+
configureOptions(options)
391415
},
392416
true,
393417
)

0 commit comments

Comments
 (0)