@@ -169,6 +169,26 @@ void annotatedAsyncCallShouldBeObservedAndErrorRecorded() {
169169 .isEqualTo (simulatedException );
170170 }
171171
172+ @ Test
173+ void observationShouldNotLeakToFutureCompletionThread () {
174+ registry .observationConfig ().observationHandler (new ObservationTextPublisher ());
175+
176+ AspectJProxyFactory pf = new AspectJProxyFactory (new ObservedService ());
177+ pf .addAspect (new ObservedAspect (registry ));
178+
179+ ObservedService service = pf .getProxy ();
180+ FakeAsyncTask fakeAsyncTask = new FakeAsyncTask ("test-result" );
181+
182+ ExecutorService executor = Executors .newSingleThreadExecutor ();
183+ CompletableFuture <String > asyncResult = service .supply (() -> service .async (fakeAsyncTask , executor ));
184+ // must run in the thread of the executor (async task)
185+ CompletableFuture <Void > asyncAssertion = asyncResult
186+ .thenRunAsync (() -> assertThat (registry ).doesNotHaveAnyRemainingCurrentObservation (), executor );
187+ fakeAsyncTask .proceed ();
188+
189+ assertThat (asyncAssertion ).succeedsWithin (Duration .ofMillis (200 ));
190+ }
191+
172192 @ Test
173193 void customObservationConventionShouldBeUsed () {
174194 registry .observationConfig ().observationHandler (new ObservationTextPublisher ());
@@ -391,14 +411,28 @@ void error() {
391411
392412 @ Observed (name = "test.async" )
393413 CompletableFuture <String > async (FakeAsyncTask fakeAsyncTask ) {
394- System .out .println ("async" );
395414 ContextSnapshot contextSnapshot = ContextSnapshotFactory .builder ()
396415 .captureKeyPredicate (key -> true )
397416 .contextRegistry (ContextRegistry .getInstance ())
398417 .build ()
399418 .captureAll ();
400- return CompletableFuture .supplyAsync (fakeAsyncTask ,
401- contextSnapshot .wrapExecutor (Executors .newSingleThreadExecutor ()));
419+ return supplyAsync (fakeAsyncTask , contextSnapshot .wrapExecutor (Executors .newSingleThreadExecutor ()));
420+ }
421+
422+ @ Observed (name = "test.async" )
423+ CompletableFuture <String > async (FakeAsyncTask fakeAsyncTask , Executor singleThreadExecutor ) {
424+ return supplyAsync (fakeAsyncTask , singleThreadExecutor );
425+ }
426+
427+ @ Observed (name = "test.supply" )
428+ <T > T supply (Supplier <T > supplier ) {
429+ System .out .println ("supply" );
430+ return supplier .get ();
431+ }
432+
433+ private CompletableFuture <String > supplyAsync (FakeAsyncTask fakeAsyncTask , Executor executor ) {
434+ System .out .println ("async" );
435+ return CompletableFuture .supplyAsync (fakeAsyncTask , executor );
402436 }
403437
404438 }
0 commit comments