Hi,

Given the ongoing context data propagation in three Github
issues/PRs/discussions (cf. [1], [2] and [3]). I think we should move
the debate to the mailing list, which guarantees the maximal reachout.

== Problem summary

We have two different problems regarding context data in log files:

1. Raman and Mikko would like to bind context data to an object
implementing the `Logger` interface or more generally to a service
object (e.g. resource manager, DAO and variants),
2. Other users would like to bind context data to a processing
pipeline, regardless of which threads it uses.

== Possible solutions

As far as I know there are currently the following approaches we can
take for problem 1:

* we can add a list of `<Property>` elements in the configuration of a
`<Logger>`, which will add the given keys to all loggers using that
configuration. This is something we can do for very static data, e.g.
we can add to each log statement the name of the library that issued
it.
* we can create a `Logger` wrapper "bound" to context data as Mikko
does. This wrapper will take care of setting the `ThreadContext`
before the logger call and restore it after it.

For problem 2, the traditional solution was provided by the
inheritability of `ThreadLocal`s, but this approach only works if the
current thread creates new ones, it does not work with thread pools.

Now there seems to be another emerging solution provided by the
`context-propagation` [9] library and explained by Dariusz Jędrzejczyk
in his blog series ([6], [7] and [8]), that allows "context-aware
runnables" to propagate context data, when they jump threads.
The library allows users to register `ThreadLocalAccessor`s that take
the snapshot of a `ThreadLocal` containing context data before a jump
and restore it on the new thread. It is used by at least Spring
Reactor.

== My preferences

Personally I think that in the short term we should:

1. deprecate `isThreadContextMapInheritable`, because it does not
correspond any more to the current pattern of concurrent programming.
It also provides a false sense of safety: a unit test using
`isThreadContextMapInheritable` will probably succeed, since each test
creates its own thread pool, but the context will be lost in
production,
2. provide a direct access to the thread locals used by
`ThreadContextMap`, so that we can submit a Log4j specific
`ThreadLocalAccessor` to the `context-propagation` project,

Regarding problem 1, I don't know what the best approach would be.
Maybe we can add `withContextData` to `LogBuilder` and create a
`BoundLogger` interface with methods to create `LogBuilder` instance
pre-filled with some context data.

Piotr

[1] https://github.com/apache/logging-log4j2/discussions/2214
[2] https://github.com/apache/logging-log4j2/pull/2385
[3] https://github.com/apache/logging-log4j-kotlin/issues/71
[4] https://stackoverflow.com/q/76498742/11748454
[5] 
https://spring.io/blog/2023/03/28/context-propagation-with-project-reactor-1-the-basics
[6] 
https://spring.io/blog/2023/03/29/context-propagation-with-project-reactor-2-the-bumpy-road-of-spring-cloud
[7] 
https://spring.io/blog/2023/03/30/context-propagation-with-project-reactor-3-unified-bridging-between-reactive
[8] https://github.com/micrometer-metrics/context-propagation

Reply via email to