When using StructuredTaskScope
from JEP 453 in Java 21+ and forking multiple tasks, I'd like to have MDC values propagated to the forks, so that all logs are properly correlated.
Extending the example from the JEP, I'd like all three logs to carry the same MDC values:
Response handle() throws ExecutionException, InterruptedException {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// TODO: set MDC "somehow"
Supplier<String> user = scope.fork(() -> logger.info("1"));
Supplier<Integer> order = scope.fork(() -> logger.info("2"));
scope.join().throwIfFailed();
logger.info("3");
return new Response(user.get(), order.get());
}
}
The problem is that MDCs aren't inherited, which might be less of a problem in pre-virtual-threads Java. However, now that creating new threads is cheap & encouraged, inheriting MDCs might be much more useful and common.
My initial attempts to solve this centred around using ScopedValue
s (JEP 429). Unlike ThreadLocal
s, such values are inherited by scope's forks, so they seem good candidates to carry the MDC markers.
To implement this, I'd have to either directly access a ScopedValue
from within Logback's logging components (is that possible?), or to manipulate the MDC. I tried overwriting the MDCAdapter
, but this has failed (Logback doesn't seem to use e.g. MDCAdapter.get
to actually read the MDC's value).
ScopedValueServiceProvider
was the component that I was missing - thank you! That answers the question, though you probably might write a proper answer (not in a comment), so that it can get accepted. – MetanephrosLogbackServiceProvider
which is not good, but ... – Security