3030import ch .qos .logback .classic .spi .ILoggingEvent ;
3131import ch .qos .logback .core .Appender ;
3232import com .google .common .collect .ImmutableMap ;
33+ import com .google .common .util .concurrent .MoreExecutors ;
34+ import com .palantir .tracing .api .OpenSpan ;
3335import com .palantir .tracing .api .Span ;
3436import com .palantir .tracing .api .SpanType ;
3537import java .net .Inet4Address ;
3638import java .net .Inet6Address ;
3739import java .net .InetAddress ;
3840import java .nio .charset .StandardCharsets ;
3941import java .util .Map ;
42+ import java .util .concurrent .ExecutorService ;
4043import java .util .stream .Collectors ;
4144import org .jmock .lib .concurrent .DeterministicScheduler ;
4245import org .junit .After ;
5659
5760public final class AsyncSlf4jSpanObserverTest {
5861
62+ private static final String TEST_OBSERVER = "test" ;
5963 private static final AsyncSlf4jSpanObserver .ZipkinCompatEndpoint DUMMY_ENDPOINT =
6064 ImmutableZipkinCompatEndpoint .builder ()
6165 .serviceName ("" )
@@ -80,17 +84,19 @@ public void before() {
8084
8185 originalLevel = logger .getLevel ();
8286 logger .setLevel (Level .TRACE );
87+ Tracer .unsubscribe (TEST_OBSERVER );
8388 }
8489
8590 @ After
8691 public void after () {
8792 logger .setLevel (originalLevel );
93+ Tracer .unsubscribe (TEST_OBSERVER );
8894 }
8995
9096 @ Test
9197 public void testJsonFormatToLog () throws Exception {
9298 DeterministicScheduler executor = new DeterministicScheduler ();
93- Tracer .subscribe ("" , AsyncSlf4jSpanObserver .of (
99+ Tracer .subscribe (TEST_OBSERVER , AsyncSlf4jSpanObserver .of (
94100 "serviceName" , Inet4Address .getLoopbackAddress (), logger , executor ));
95101 Tracer .startSpan ("operation" );
96102 Span span = Tracer .completeSpan ().get ();
@@ -106,13 +112,12 @@ public void testJsonFormatToLog() throws Exception {
106112 assertThat (event .getValue ().getFormattedMessage ())
107113 .isEqualTo (AsyncSlf4jSpanObserver .ZipkinCompatSpan .fromSpan (span , expectedEndpoint ).toJson ());
108114 verifyNoMoreInteractions (appender );
109- Tracer .unsubscribe ("" );
110115 }
111116
112117 @ Test
113118 public void testDefaultConstructorDeterminesIpAddress () throws Exception {
114119 DeterministicScheduler executor = new DeterministicScheduler ();
115- Tracer .subscribe ("" , AsyncSlf4jSpanObserver .of ("serviceName" , executor ));
120+ Tracer .subscribe (TEST_OBSERVER , AsyncSlf4jSpanObserver .of ("serviceName" , executor ));
116121 Tracer .startSpan ("operation" );
117122 Span span = Tracer .completeSpan ().get ();
118123
@@ -131,7 +136,6 @@ public void testDefaultConstructorDeterminesIpAddress() throws Exception {
131136
132137 assertThat (event .getValue ().getFormattedMessage ())
133138 .isEqualTo (AsyncSlf4jSpanObserver .ZipkinCompatSpan .fromSpan (span , expectedEndpoint .build ()).toJson ());
134- Tracer .unsubscribe ("" );
135139 }
136140
137141 @ Test
@@ -219,6 +223,38 @@ public void testSpanMetadataConvertsToZipkinBinaryAnnotations() {
219223 assertThat (annotationMap ).isEqualTo (spanMetadata );
220224 }
221225
226+ @ Test
227+ public void testCompleteSpanAfterExecutorShutdown () {
228+ ExecutorService executor = MoreExecutors .newDirectExecutorService ();
229+ Tracer .subscribe (TEST_OBSERVER , AsyncSlf4jSpanObserver .of (
230+ "serviceName" , Inet4Address .getLoopbackAddress (), logger , executor ));
231+ OpenSpan span1 = Tracer .startSpan ("operation" );
232+ assertThat (Tracer .completeSpan ()).isPresent ().get ()
233+ .extracting ("spanId" , "operation" )
234+ .contains (span1 .getSpanId (), span1 .getOperation ());
235+
236+ OpenSpan span2 = Tracer .startSpan ("operation" );
237+ executor .shutdown ();
238+ assertThat (Tracer .completeSpan ()).isPresent ().get ()
239+ .extracting ("spanId" , "operation" )
240+ .contains (span2 .getSpanId (), span2 .getOperation ());
241+ }
242+
243+ @ Test
244+ public void testFastCompleteSpanAfterExecutorShutdown () {
245+ ExecutorService executor = MoreExecutors .newDirectExecutorService ();
246+ Tracer .subscribe (TEST_OBSERVER , AsyncSlf4jSpanObserver .of (
247+ "serviceName" , Inet4Address .getLoopbackAddress (), logger , executor ));
248+ OpenSpan span1 = Tracer .startSpan ("operation" );
249+ assertThat (Tracer .completeSpan ()).isPresent ().get ()
250+ .extracting ("spanId" , "operation" )
251+ .contains (span1 .getSpanId (), span1 .getOperation ());
252+
253+ Tracer .startSpan ("operation" );
254+ executor .shutdown ();
255+ Tracer .fastCompleteSpan ();
256+ }
257+
222258 private static AsyncSlf4jSpanObserver .ZipkinCompatSpan zipkinSpan (long start , long duration , SpanType type ) {
223259 Span span = Span .builder ()
224260 .traceId ("" )
0 commit comments