Skip to content

Commit 17d6e2a

Browse files
authored
Merge branch 'main' into feat/scopes-chain-debug-util
2 parents ee800b4 + 2fbb2e3 commit 17d6e2a

9 files changed

Lines changed: 40 additions & 81 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@
2121
- `SentryAttribute.stringAttribute()` takes a `String` value
2222
- We opted for handling parameters via `SentryLogParameters` to avoid creating tons of overloads that are ambiguous.
2323

24+
### Fixes
25+
26+
- Isolation scope is now forked in `OtelSentrySpanProcessor` instead of `OtelSentryPropagator` ([#4434](https://github.com/getsentry/sentry-java/pull/4434))
27+
- Since propagator may never be invoked we moved the location where isolation scope is forked.
28+
- Not invoking `OtelSentryPropagator.extract` or having a `sentry-trace` header that failed to parse would cause isolation scope not to be forked.
29+
- This in turn caused data to bleed between scopes, e.g. from one request into another
30+
31+
### Dependencies
32+
33+
- Bump Spring Boot to `3.5.0` ([#4111](https://github.com/getsentry/sentry-java/pull/4111))
34+
2435
## 8.12.0
2536

2637
### Features

buildSrc/src/main/java/Config.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ object Config {
66
val kotlinStdLib = "stdlib-jdk8"
77

88
val springBootVersion = "2.7.18"
9-
val springBoot3Version = "3.4.2"
9+
val springBoot3Version = "3.5.0"
1010
val kotlinCompatibleLanguageVersion = "1.6"
1111

1212
val androidComposeCompilerVersion = "1.5.14"

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ kotlin = "1.9.24"
99
# see https://developer.android.com/jetpack/androidx/releases/compose-kotlin
1010
okhttp = "4.9.2"
1111
springTwo = "2.7.18"
12-
springThree = "3.4.2"
12+
springThree = "3.5.0"
1313
targetSdk = "34"
1414
compileSdk = "34"
1515
minSdk = "21"

sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OtelSentryPropagator.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package io.sentry.opentelemetry;
22

3-
import static io.sentry.opentelemetry.SentryOtelKeys.SENTRY_SCOPES_KEY;
4-
53
import io.opentelemetry.api.common.Attributes;
64
import io.opentelemetry.api.trace.Span;
75
import io.opentelemetry.api.trace.SpanContext;
@@ -15,7 +13,6 @@
1513
import io.sentry.BaggageHeader;
1614
import io.sentry.IScopes;
1715
import io.sentry.ScopesAdapter;
18-
import io.sentry.Sentry;
1916
import io.sentry.SentryLevel;
2017
import io.sentry.SentryOptions;
2118
import io.sentry.SentryTraceHeader;
@@ -105,16 +102,10 @@ public <C> void inject(final Context context, final C carrier, final TextMapSett
105102
@Override
106103
public <C> Context extract(
107104
final Context context, final C carrier, final TextMapGetter<C> getter) {
108-
final @Nullable IScopes scopesFromParentContext = context.get(SENTRY_SCOPES_KEY);
109-
final @NotNull IScopes scopesToUse =
110-
scopesFromParentContext != null
111-
? scopesFromParentContext.forkedScopes("propagator")
112-
: Sentry.forkedRootScopes("propagator");
113-
114105
final @Nullable String sentryTraceString =
115106
getter.get(carrier, SentryTraceHeader.SENTRY_TRACE_HEADER);
116107
if (sentryTraceString == null) {
117-
return context.with(SENTRY_SCOPES_KEY, scopesToUse);
108+
return context;
118109
}
119110

120111
try {
@@ -136,7 +127,6 @@ public <C> Context extract(
136127
final @NotNull Context modifiedContext =
137128
context
138129
.with(wrappedSpan)
139-
.with(SENTRY_SCOPES_KEY, scopesToUse)
140130
.with(SentryOtelKeys.SENTRY_TRACE_KEY, sentryTraceHeader)
141131
.with(SentryOtelKeys.SENTRY_BAGGAGE_KEY, baggage);
142132

sentry-opentelemetry/sentry-opentelemetry-core/src/main/java/io/sentry/opentelemetry/OtelSentrySpanProcessor.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.opentelemetry.sdk.trace.SpanProcessor;
1111
import io.opentelemetry.sdk.trace.data.EventData;
1212
import io.opentelemetry.sdk.trace.data.ExceptionEventData;
13+
import io.opentelemetry.sdk.trace.data.SpanData;
1314
import io.sentry.Baggage;
1415
import io.sentry.DateUtils;
1516
import io.sentry.IScopes;
@@ -48,11 +49,7 @@ public void onStart(final @NotNull Context parentContext, final @NotNull ReadWri
4849
return;
4950
}
5051

51-
final @Nullable IScopes scopesFromContext = parentContext.get(SENTRY_SCOPES_KEY);
52-
final @NotNull IScopes scopes =
53-
scopesFromContext != null
54-
? scopesFromContext.forkedCurrentScope("spanprocessor")
55-
: Sentry.forkedRootScopes("spanprocessor");
52+
final @NotNull IScopes scopes = forkScopes(parentContext, otelSpan.toSpanData());
5653

5754
final @Nullable IOtelSpanWrapper sentryParentSpan =
5855
spanStorage.getSentrySpan(otelSpan.getParentSpanContext());
@@ -111,6 +108,22 @@ public void onStart(final @NotNull Context parentContext, final @NotNull ReadWri
111108
spanStorage.storeSentrySpan(spanContext, sentrySpan);
112109
}
113110

111+
private IScopes forkScopes(final @NotNull Context context, final @NotNull SpanData span) {
112+
final @Nullable IScopes scopesFromContext = context.get(SENTRY_SCOPES_KEY);
113+
if (scopesFromContext == null) {
114+
return Sentry.forkedRootScopes("spanprocessor.new");
115+
}
116+
if (isRootSpan(span)) {
117+
return scopesFromContext.forkedScopes("spanprocessor.rootspan");
118+
}
119+
120+
return scopesFromContext.forkedCurrentScope("spanprocessor.nonrootspan");
121+
}
122+
123+
private boolean isRootSpan(SpanData otelSpan) {
124+
return !otelSpan.getParentSpanContext().isValid() || otelSpan.getParentSpanContext().isRemote();
125+
}
126+
114127
private @Nullable Boolean isSampled(
115128
final @NotNull ReadWriteSpan otelSpan,
116129
final @Nullable TracesSamplingDecision samplingDecision) {

sentry-opentelemetry/sentry-opentelemetry-core/src/test/kotlin/OtelSentryPropagatorTest.kt

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -47,62 +47,6 @@ class OtelSentryPropagatorTest {
4747
assertEquals(listOf("sentry-trace", "baggage"), propagator.fields())
4848
}
4949

50-
@Test
51-
fun `forks root scopes if none in context without headers`() {
52-
val propagator = OtelSentryPropagator()
53-
val carrier: Map<String, String> = mapOf()
54-
55-
val newContext = propagator.extract(Context.root(), carrier, MapGetter())
56-
57-
val scopes = newContext.get(SENTRY_SCOPES_KEY)
58-
assertNotNull(scopes)
59-
assertSame(Sentry.forkedRootScopes("test").parentScopes, scopes.parentScopes)
60-
}
61-
62-
@Test
63-
fun `forks scopes from context if present without headers`() {
64-
val propagator = OtelSentryPropagator()
65-
val carrier: Map<String, String> = mapOf()
66-
val scopeInContext = Sentry.forkedRootScopes("test")
67-
68-
val newContext = propagator.extract(Context.root().with(SENTRY_SCOPES_KEY, scopeInContext), carrier, MapGetter())
69-
70-
val scopes = newContext.get(SENTRY_SCOPES_KEY)
71-
assertNotNull(scopes)
72-
assertSame(scopeInContext, scopes.parentScopes)
73-
}
74-
75-
@Test
76-
fun `forks root scopes if none in context with headers`() {
77-
val propagator = OtelSentryPropagator()
78-
val carrier: Map<String, String> = mapOf(
79-
"sentry-trace" to "f9118105af4a2d42b4124532cd1065ff-424cffc8f94feeee-1",
80-
"baggage" to "sentry-environment=production,sentry-public_key=502f25099c204a2fbf4cb16edc5975d1,sentry-sample_rand=0.456789,sentry-sample_rate=0.5,sentry-sampled=true,sentry-trace_id=df71f5972f754b4c85af13ff5c07017d"
81-
)
82-
83-
val newContext = propagator.extract(Context.root(), carrier, MapGetter())
84-
85-
val scopes = newContext.get(SENTRY_SCOPES_KEY)
86-
assertNotNull(scopes)
87-
assertSame(Sentry.forkedRootScopes("test").parentScopes, scopes.parentScopes)
88-
}
89-
90-
@Test
91-
fun `forks scopes from context if present with headers`() {
92-
val propagator = OtelSentryPropagator()
93-
val carrier: Map<String, String> = mapOf(
94-
"sentry-trace" to "f9118105af4a2d42b4124532cd1065ff-424cffc8f94feeee-1",
95-
"baggage" to "sentry-environment=production,sentry-public_key=502f25099c204a2fbf4cb16edc5975d1,sentry-sample_rand=0.456789,sentry-sample_rate=0.5,sentry-sampled=true,sentry-trace_id=df71f5972f754b4c85af13ff5c07017d"
96-
)
97-
val scopeInContext = Sentry.forkedRootScopes("test")
98-
99-
val newContext = propagator.extract(Context.root().with(SENTRY_SCOPES_KEY, scopeInContext), carrier, MapGetter())
100-
101-
val scopes = newContext.get(SENTRY_SCOPES_KEY)
102-
assertNotNull(scopes)
103-
assertSame(scopeInContext, scopes.parentScopes)
104-
}
105-
10650
@Test
10751
fun `invalid sentry trace header returns context without modification`() {
10852
val propagator = OtelSentryPropagator()

sentry-samples/sentry-samples-spring-boot-jakarta/src/main/java/io/sentry/samples/spring/boot/jakarta/graphql/TaskCreatorController.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public TaskCreatorController(final BatchLoaderRegistry batchLoaderRegistry) {
2020
// using mapped BatchLoader to not have to deal with correct ordering of items
2121
batchLoaderRegistry
2222
.forTypePair(String.class, ProjectController.Creator.class)
23+
.withOptions((builder) -> builder.setBatchingEnabled(true))
2324
.registerMappedBatchLoader(
2425
(Set<String> keys, BatchLoaderEnvironment env) -> {
2526
return Mono.fromCallable(

sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public BatchLoaderRegistry.RegistrationSpec<K, V> withName(String name) {
7676

7777
@Override
7878
public BatchLoaderRegistry.RegistrationSpec<K, V> withOptions(
79-
Consumer<DataLoaderOptions> optionsConsumer) {
79+
Consumer<DataLoaderOptions.Builder> optionsConsumer) {
8080
return delegate.withOptions(optionsConsumer);
8181
}
8282

sentry-spring-jakarta/src/test/kotlin/io/sentry/spring/jakarta/graphql/SentrySpringSubscriptionHandlerTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
package io.sentry.spring.graphql
1+
package io.sentry.spring.jakarta.graphql
22

33
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters
44
import graphql.language.Document
55
import graphql.language.OperationDefinition
66
import graphql.schema.DataFetchingEnvironment
77
import io.sentry.IScopes
88
import io.sentry.graphql.ExceptionReporter
9-
import io.sentry.spring.jakarta.graphql.SentrySpringSubscriptionHandler
109
import org.junit.jupiter.api.assertThrows
1110
import org.mockito.kotlin.anyOrNull
11+
import org.mockito.kotlin.check
1212
import org.mockito.kotlin.mock
1313
import org.mockito.kotlin.same
1414
import org.mockito.kotlin.verify
@@ -40,10 +40,10 @@ class SentrySpringSubscriptionHandlerTest {
4040

4141
verify(exceptionReporter).captureThrowable(
4242
same(exception),
43-
org.mockito.kotlin.check {
43+
check {
4444
assertEquals(true, it.isSubscription)
4545
assertSame(scopes, it.scopes)
46-
assertEquals("query testQuery\n", it.query)
46+
assertEquals("query testQuery \n", it.query)
4747
},
4848
anyOrNull()
4949
)
@@ -69,10 +69,10 @@ class SentrySpringSubscriptionHandlerTest {
6969

7070
verify(exceptionReporter).captureThrowable(
7171
same(exception),
72-
org.mockito.kotlin.check {
72+
check {
7373
assertEquals(true, it.isSubscription)
7474
assertSame(scopes, it.scopes)
75-
assertEquals("query testQuery\n", it.query)
75+
assertEquals("query testQuery \n", it.query)
7676
},
7777
anyOrNull()
7878
)

0 commit comments

Comments
 (0)