2323import io .opentelemetry .api .trace .Span ;
2424import io .opentelemetry .api .trace .SpanContext ;
2525import io .opentelemetry .api .trace .StatusCode ;
26- import io .opentelemetry .api .trace .TraceId ;
2726import io .opentelemetry .context .Context ;
2827import io .opentelemetry .context .ContextKey ;
2928import io .opentelemetry .context .ContextStorage ;
@@ -49,9 +48,8 @@ void currentContextComesFromOpenTelemetryContextStorage() {
4948 }
5049
5150 @ Test
52- void noActiveSpanBeforeFirstSpanInTraceIsAttachedToContext () {
53- var traceId = IdGenerator .random ().generateTraceId ();
54- assertEquals (Optional .empty (), spanTracker .getActiveSpan (traceId ));
51+ void noActiveSpanForThreadBeforeFirstSpanInTraceIsAttachedToContext () {
52+ assertEquals (Optional .empty (), spanTracker .getActiveSpan (currentThreadId ()));
5553 }
5654
5755 @ Test
@@ -62,8 +60,7 @@ void trackActiveSpanWhenNewContextAttached() {
6260 registry .register (spanContext );
6361
6462 try (var ignored = spanTracker .attach (context )) {
65- var traceId = span .getSpanContext ().getTraceId ();
66- assertEquals (Optional .of (spanContext ), spanTracker .getActiveSpan (traceId ));
63+ assertEquals (Optional .of (spanContext ), spanTracker .getActiveSpan (currentThreadId ()));
6764 }
6865 }
6966
@@ -77,7 +74,7 @@ void noActiveSpanForTraceAfterSpansScopeIsClosed() {
7774 var scope = spanTracker .attach (context );
7875 scope .close ();
7976
80- assertEquals (Optional .empty (), spanTracker .getActiveSpan (spanContext . getTraceId ()));
77+ assertEquals (Optional .empty (), spanTracker .getActiveSpan (currentThreadId ()));
8178 }
8279
8380 @ Test
@@ -91,8 +88,7 @@ void trackActiveSpanAcrossMultipleContextChanges() {
9188 var spanContext = span .getSpanContext ();
9289 context = context .with (span );
9390 try (var ignoredScope2 = spanTracker .attach (context )) {
94- var traceId = span .getSpanContext ().getTraceId ();
95- assertEquals (Optional .of (spanContext ), spanTracker .getActiveSpan (traceId ));
91+ assertEquals (Optional .of (spanContext ), spanTracker .getActiveSpan (currentThreadId ()));
9692 }
9793 }
9894 }
@@ -111,42 +107,100 @@ void restoreActiveSpanToPreviousSpanAfterScopeClosing() {
111107 scope .close ();
112108
113109 var rootSpanContext = root .getSpanContext ();
114- assertEquals (
115- Optional .of (rootSpanContext ), spanTracker .getActiveSpan (rootSpanContext .getTraceId ()));
110+ assertEquals (Optional .of (rootSpanContext ), spanTracker .getActiveSpan (currentThreadId ()));
116111 }
117112 }
118113
119114 @ Test
120115 void trackActiveSpanForMultipleTraces () throws Exception {
121- var executor = Executors . newSingleThreadExecutor ( );
122- var root1 = FakeSpan .newSpan (Snapshotting .spanContext ());
123- var root2 = FakeSpan . newSpan ( Snapshotting . spanContext ());
124- registry .register (root1 .getSpanContext ());
125- registry . register ( root2 . getSpanContext ());
126-
127- try (var ignoredScope1 = executor .submit (attach (root1 )).get ();
128- var ignoredScope2 = executor .submit (attach (root2 )).get ()) {
129- var traceId1 = root1 . getSpanContext (). getTraceId ();
130- assertEquals ( Optional .of (root1 .getSpanContext ()), spanTracker .getActiveSpan (traceId1 ));
131- var traceId2 = root2 . getSpanContext (). getTraceId ();
132- assertEquals ( Optional .of (root2 .getSpanContext ()), spanTracker .getActiveSpan (traceId2 ));
116+ var span1 = FakeSpan . newSpan ( Snapshotting . spanContext () );
117+ var span2 = FakeSpan .newSpan (Snapshotting .spanContext ());
118+ registry . register ( span1 . getSpanContext ());
119+ registry .register (span2 .getSpanContext ());
120+
121+ var executor = Executors . newFixedThreadPool ( 2 );
122+ try (var scope1 = executor .submit (attach (span1 )).get ();
123+ var scope2 = executor .submit (attach (span2 )).get ()) {
124+ assertEquals (
125+ Optional .of (span1 .getSpanContext ()), spanTracker .getActiveSpan (scope1 . getThreadId () ));
126+ assertEquals (
127+ Optional .of (span2 .getSpanContext ()), spanTracker .getActiveSpan (scope2 . getThreadId () ));
133128 } finally {
134129 executor .shutdown ();
135130 }
136131 }
137132
138- private Callable <Scope > attach (Span span ) {
133+ @ Test
134+ void trackMultipleActiveSpansForSameTraceFromDifferentThreads () throws Exception {
135+ var traceId = IdGenerator .random ().generateTraceId ();
136+ var span1 = FakeSpan .newSpan (Snapshotting .spanContext ().withTraceId (traceId ));
137+ var span2 = FakeSpan .newSpan (Snapshotting .spanContext ().withTraceId (traceId ));
138+ registry .register (span1 .getSpanContext ());
139+ registry .register (span2 .getSpanContext ());
140+
141+ var executor = Executors .newFixedThreadPool (2 );
142+ try (var scope1 = executor .submit (attach (span1 )).get ();
143+ var scope2 = executor .submit (attach (span2 )).get ()) {
144+ assertEquals (
145+ Optional .of (span1 .getSpanContext ()), spanTracker .getActiveSpan (scope1 .getThreadId ()));
146+ assertEquals (
147+ Optional .of (span2 .getSpanContext ()), spanTracker .getActiveSpan (scope2 .getThreadId ()));
148+ } finally {
149+ executor .shutdown ();
150+ }
151+ }
152+
153+ private Callable <ThreadScope > attach (Span span ) {
139154 return () -> {
140155 var context = Context .root ().with (span );
141- return spanTracker .attach (context );
156+ return new ThreadScope ( spanTracker .attach (context ), Thread . currentThread (). getId () );
142157 };
143158 }
144159
160+ private static class ThreadScope implements Scope {
161+ private final Scope scope ;
162+ private final long threadId ;
163+
164+ private ThreadScope (Scope scope , long threadId ) {
165+ this .scope = scope ;
166+ this .threadId = threadId ;
167+ }
168+
169+ public long getThreadId () {
170+ return threadId ;
171+ }
172+
173+ @ Override
174+ public void close () {
175+ scope .close ();
176+ }
177+ }
178+
179+ @ Test
180+ void activeSpanForThreadIsUnchangedWhenTraceStartsSpanInAnotherThread () throws Exception {
181+ var traceId = IdGenerator .random ().generateTraceId ();
182+ var root = FakeSpan .newSpan (Snapshotting .spanContext ().withTraceId (traceId ));
183+ var child = FakeSpan .newSpan (Snapshotting .spanContext ().withTraceId (traceId ));
184+ registry .register (root .getSpanContext ());
185+ registry .register (child .getSpanContext ());
186+
187+ var executor = Executors .newSingleThreadExecutor ();
188+ try (var scope1 = attach (root ).call ();
189+ var scope2 = executor .submit (attach (child )).get ()) {
190+ assertEquals (
191+ Optional .of (root .getSpanContext ()), spanTracker .getActiveSpan (scope1 .getThreadId ()));
192+ assertEquals (
193+ Optional .of (child .getSpanContext ()), spanTracker .getActiveSpan (scope2 .getThreadId ()));
194+ } finally {
195+ executor .shutdown ();
196+ }
197+ }
198+
145199 @ Test
146200 void doNotTrackSpanWhenNoSpanPresentInContext () {
147201 var context = Context .root ().with (ContextKey .named ("test-key" ), "value" );
148202 try (var ignored = spanTracker .attach (context )) {
149- assertEquals (Optional .empty (), spanTracker .getActiveSpan (TraceId . getInvalid ()));
203+ assertEquals (Optional .empty (), spanTracker .getActiveSpan (currentThreadId ()));
150204 }
151205 }
152206
@@ -157,8 +211,7 @@ void doNotTrackSpanWhenSpanIsNotSampled() {
157211 registry .register (span .getSpanContext ());
158212
159213 try (var ignored = spanTracker .attach (context )) {
160- var traceId = span .getSpanContext ().getTraceId ();
161- assertEquals (Optional .empty (), spanTracker .getActiveSpan (traceId ));
214+ assertEquals (Optional .empty (), spanTracker .getActiveSpan (currentThreadId ()));
162215 }
163216 }
164217
@@ -170,8 +223,7 @@ void doNotTrackSpanTraceIsNotRegisteredForSnapshotting() {
170223 var context = Context .root ().with (span );
171224
172225 try (var ignored = spanTracker .attach (context )) {
173- var traceId = span .getSpanContext ().getTraceId ();
174- assertEquals (Optional .empty (), spanTracker .getActiveSpan (traceId ));
226+ assertEquals (Optional .empty (), spanTracker .getActiveSpan (currentThreadId ()));
175227 }
176228 }
177229
@@ -191,6 +243,10 @@ void doNotTrackContinuallyTrackSameSpan() {
191243 }
192244 }
193245
246+ private long currentThreadId () {
247+ return Thread .currentThread ().getId ();
248+ }
249+
194250 private static class FakeSpan implements Span {
195251 static FakeSpan newSpan (Snapshotting .SpanContextBuilder spanContext ) {
196252 return new FakeSpan (spanContext .build ());
0 commit comments