Skip to content

Commit 8d977f6

Browse files
Merge branch '1.0.x'
2 parents dc6cd9c + b6022ca commit 8d977f6

File tree

3 files changed

+68
-4
lines changed

3 files changed

+68
-4
lines changed

micrometer-tracing-bridges/micrometer-tracing-bridge-brave/src/test/java/io/micrometer/tracing/brave/handler/DefaultTracingObservationHandlerBraveTests.java

+28
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import brave.Tracing;
1919
import brave.handler.MutableSpan;
2020
import brave.test.TestSpanHandler;
21+
import io.micrometer.context.ContextSnapshot;
2122
import io.micrometer.observation.Observation;
2223
import io.micrometer.observation.Observation.Event;
2324
import io.micrometer.observation.ObservationRegistry;
@@ -38,6 +39,7 @@
3839
import java.io.IOException;
3940
import java.util.List;
4041
import java.util.Map;
42+
import java.util.concurrent.atomic.AtomicReference;
4143
import java.util.stream.Collectors;
4244

4345
import static org.assertj.core.api.BDDAssertions.then;
@@ -189,6 +191,32 @@ void should_put_and_remove_trace_from_thread_local_on_scope_change_for_the_same_
189191
then(tracer.currentSpan()).isNull();
190192
}
191193

194+
@Test
195+
void should_not_break_when_dealing_with_threads() throws InterruptedException {
196+
ObservationRegistry registry = ObservationRegistry.create();
197+
registry.observationConfig().observationHandler(handler);
198+
199+
Observation parent = Observation.start("parent", registry);
200+
Span parentSpan = getSpanFromObservation(parent);
201+
202+
then(parentSpan).isNotNull();
203+
204+
try (Observation.Scope scope = parent.openScope()) {
205+
then(tracer.currentSpan()).isEqualTo(parentSpan);
206+
AtomicReference<Span> span = new AtomicReference<>();
207+
new Thread(ContextSnapshot.captureAll().wrap(() -> {
208+
span.set(tracer.currentSpan());
209+
})).start();
210+
211+
Thread.sleep(100);
212+
213+
then(span.get()).isEqualTo(parentSpan);
214+
then(tracer.currentSpan()).isEqualTo(parentSpan);
215+
}
216+
217+
then(tracer.currentSpan()).isNull();
218+
}
219+
192220
private static Span getSpanFromObservation(Observation parent) {
193221
TracingObservationHandler.TracingContext tracingContext = parent.getContextView().getOrDefault(
194222
TracingObservationHandler.TracingContext.class, new TracingObservationHandler.TracingContext());

micrometer-tracing-bridges/micrometer-tracing-bridge-otel/src/test/java/io/micrometer/tracing/otel/handler/DefaultTracingObservationHandlerOtelTests.java

+28
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package io.micrometer.tracing.otel.handler;
1717

18+
import io.micrometer.context.ContextSnapshot;
1819
import io.micrometer.observation.Observation;
1920
import io.micrometer.observation.Observation.Event;
2021
import io.micrometer.observation.ObservationRegistry;
@@ -41,6 +42,7 @@
4142
import java.util.Collections;
4243
import java.util.List;
4344
import java.util.Queue;
45+
import java.util.concurrent.atomic.AtomicReference;
4446
import java.util.stream.Collectors;
4547

4648
import static org.assertj.core.api.BDDAssertions.then;
@@ -208,6 +210,32 @@ void should_signal_events() {
208210
then(data.getEvents()).hasSize(1).element(0).extracting(EventData::getName).isEqualTo("bar");
209211
}
210212

213+
@Test
214+
void should_not_break_when_dealing_with_threads() throws InterruptedException {
215+
ObservationRegistry registry = ObservationRegistry.create();
216+
registry.observationConfig().observationHandler(handler);
217+
218+
Observation parent = Observation.start("parent", registry);
219+
Span parentSpan = getSpanFromObservation(parent);
220+
221+
then(parentSpan).isNotNull();
222+
223+
try (Observation.Scope scope = parent.openScope()) {
224+
then(tracer.currentSpan()).isEqualTo(parentSpan);
225+
AtomicReference<Span> span = new AtomicReference<>();
226+
new Thread(ContextSnapshot.captureAll().wrap(() -> {
227+
span.set(tracer.currentSpan());
228+
})).start();
229+
230+
Thread.sleep(100);
231+
232+
then(span.get()).isEqualTo(parentSpan);
233+
then(tracer.currentSpan()).isEqualTo(parentSpan);
234+
}
235+
236+
then(tracer.currentSpan()).isNull();
237+
}
238+
211239
private SpanData takeOnlySpan() {
212240
Queue<SpanData> spans = testSpanProcessor.spans();
213241
then(spans).hasSize(1);

micrometer-tracing/src/main/java/io/micrometer/tracing/handler/TracingObservationHandler.java

+12-4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
import io.micrometer.tracing.Tracer;
2929
import io.micrometer.tracing.internal.SpanNameUtil;
3030

31+
import java.util.Map;
32+
import java.util.concurrent.ConcurrentHashMap;
33+
3134
/**
3235
* Marker interface for tracing handlers.
3336
*
@@ -180,7 +183,7 @@ class TracingContext {
180183

181184
private Span span;
182185

183-
private CurrentTraceContext.Scope scope;
186+
Map<Thread, CurrentTraceContext.Scope> scopes = new ConcurrentHashMap<>();
184187

185188
/**
186189
* Returns the span.
@@ -203,15 +206,20 @@ public void setSpan(Span span) {
203206
* @return scope of the span
204207
*/
205208
public CurrentTraceContext.Scope getScope() {
206-
return this.scope;
209+
return this.scopes.get(Thread.currentThread());
207210
}
208211

209212
/**
210213
* Sets the current trace context scope.
211214
* @param scope scope to set
212215
*/
213216
public void setScope(CurrentTraceContext.Scope scope) {
214-
this.scope = scope;
217+
if (scope == null) {
218+
this.scopes.remove(Thread.currentThread());
219+
}
220+
else {
221+
this.scopes.put(Thread.currentThread(), scope);
222+
}
215223
}
216224

217225
/**
@@ -226,7 +234,7 @@ public void setSpanAndScope(Span span, CurrentTraceContext.Scope scope) {
226234

227235
@Override
228236
public String toString() {
229-
return "TracingContext{" + "span=" + span + ", scope=" + scope + '}';
237+
return "TracingContext{" + "span=" + span + ", scope=" + scopes + '}';
230238
}
231239

232240
}

0 commit comments

Comments
 (0)