Skip to content

Commit ce3a9e0

Browse files
Merge branch '1.14.x' into 1.15.x
2 parents c6e10e3 + bae31eb commit ce3a9e0

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

micrometer-observation/src/main/java/io/micrometer/observation/aop/ObservedAspect.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
* @author Jonatan Ivanov
7272
* @author Yanming Zhou
7373
* @author Jeonggi Kim
74+
* @author Maksim Petelin
7475
* @since 1.10.0
7576
*/
7677
@Aspect
@@ -151,16 +152,16 @@ private Object observe(ProceedingJoinPoint pjp, Method method, Observed observed
151152
try {
152153
Object result = pjp.proceed();
153154
if (result == null) {
154-
stopObservation(observation, scope, null);
155+
stopObservation(observation, null);
155156
return result;
156157
}
157158
else {
158159
CompletionStage<?> stage = (CompletionStage<?>) result;
159-
return stage.whenComplete((res, error) -> stopObservation(observation, scope, error));
160+
return stage.whenComplete((res, error) -> stopObservation(observation, error));
160161
}
161162
}
162163
catch (Throwable error) {
163-
stopObservation(observation, scope, error);
164+
stopObservation(observation, error);
164165
throw error;
165166
}
166167
finally {
@@ -191,11 +192,10 @@ private Method getMethod(ProceedingJoinPoint pjp) throws NoSuchMethodException {
191192
return method;
192193
}
193194

194-
private void stopObservation(Observation observation, Observation.Scope scope, @Nullable Throwable error) {
195+
private void stopObservation(Observation observation, @Nullable Throwable error) {
195196
if (error != null) {
196197
observation.error(error);
197198
}
198-
scope.close();
199199
observation.stop();
200200
}
201201

samples/micrometer-samples-spring-framework6/src/test/java/io/micrometer/samples/spring6/aop/ObservedAspectTests.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,26 @@ void annotatedAsyncCallShouldBeObservedAndErrorRecorded() {
170170
.isEqualTo(simulatedException);
171171
}
172172

173+
@Test
174+
void observationShouldNotLeakToFutureCompletionThread() {
175+
registry.observationConfig().observationHandler(new ObservationTextPublisher());
176+
177+
AspectJProxyFactory pf = new AspectJProxyFactory(new ObservedService());
178+
pf.addAspect(new ObservedAspect(registry));
179+
180+
ObservedService service = pf.getProxy();
181+
FakeAsyncTask fakeAsyncTask = new FakeAsyncTask("test-result");
182+
183+
ExecutorService executor = Executors.newSingleThreadExecutor();
184+
CompletableFuture<String> asyncResult = service.supply(() -> service.async(fakeAsyncTask, executor));
185+
// must run in the thread of the executor (async task)
186+
CompletableFuture<Void> asyncAssertion = asyncResult
187+
.thenRunAsync(() -> assertThat(registry).doesNotHaveAnyRemainingCurrentObservation(), executor);
188+
fakeAsyncTask.proceed();
189+
190+
assertThat(asyncAssertion).succeedsWithin(Duration.ofMillis(200));
191+
}
192+
173193
@Test
174194
void customObservationConventionShouldBeUsed() {
175195
registry.observationConfig().observationHandler(new ObservationTextPublisher());
@@ -392,14 +412,28 @@ void error() {
392412

393413
@Observed(name = "test.async")
394414
CompletableFuture<String> async(FakeAsyncTask fakeAsyncTask) {
395-
System.out.println("async");
396415
ContextSnapshot contextSnapshot = ContextSnapshotFactory.builder()
397416
.captureKeyPredicate(key -> true)
398417
.contextRegistry(ContextRegistry.getInstance())
399418
.build()
400419
.captureAll();
401-
return CompletableFuture.supplyAsync(fakeAsyncTask,
402-
contextSnapshot.wrapExecutor(Executors.newSingleThreadExecutor()));
420+
return supplyAsync(fakeAsyncTask, contextSnapshot.wrapExecutor(Executors.newSingleThreadExecutor()));
421+
}
422+
423+
@Observed(name = "test.async")
424+
CompletableFuture<String> async(FakeAsyncTask fakeAsyncTask, Executor singleThreadExecutor) {
425+
return supplyAsync(fakeAsyncTask, singleThreadExecutor);
426+
}
427+
428+
@Observed(name = "test.supply")
429+
<T> T supply(Supplier<T> supplier) {
430+
System.out.println("supply");
431+
return supplier.get();
432+
}
433+
434+
private CompletableFuture<String> supplyAsync(FakeAsyncTask fakeAsyncTask, Executor executor) {
435+
System.out.println("async");
436+
return CompletableFuture.supplyAsync(fakeAsyncTask, executor);
403437
}
404438

405439
}

0 commit comments

Comments
 (0)