Skip to content

ObservedAspect leaks observation to CompletableFuture completion thread #6727

@pema4

Description

@pema4

Describe the bug
Current ObservedAspect implementation for async methods (with return type of CompletionStage) leaks parent observation to the future completion thread.
It happens because Observation.Scope#close() method is called on the thread that completes the future.

Environment

  • Micrometer version: 1.12.2, 1.15.4
  • Micrometer registry: -
  • OS: macOS
  • Java version: openjdk version "24.0.2" 2025-07-15

To Reproduce
Here is a code snippet:

class ObservedService {
    @Observed(name = "test.child")
    CompletableFuture<?> child(Supplier<String> supplier) {
        return CompletableFuture.supplyAsync(supplier, executor); // executor is a thread pool
    }

    @Observed(name = "test.parent")
    void parent(Supplier<String> supplier) {
        child(supplier).join();
    }
}

When ObservedService#parent is called, I expect Micrometer to:

  1. open test.parent scope in thread main
  2. open test.child scope in thread main
  3. close test.child scope in thread main, scope is now test.parent
  4. close test.parent scope in thread main, scope is now null

But the actual execution is different:

  1. open test.parent scope in thread main
  2. open test.child scope in thread main
  3. close test.child scope in thread main, scope is now test.parent
  4. close test.child scope in thread pool-1-thread-1, scope is now test.parent — this is wrong
  5. close test.parent scope in thread main, scope is now null

Further attempts to call ObservedService#parent may trigger this warning — Micrometer detects an attempt to replace an incorrect observation with a new one (that is also incorrect).

Expected behavior
ObservedAspect should not open any scopes on CompletionStage completion thread.

Additional context
I will attach a PR with a reproducer and a probable fix.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions