revisiting MDC in slf4j broken because of CompletableFuture
Ralph Goers
ralph.goers at dslextreme.com
Thu Mar 22 17:13:28 UTC 2018
Log4j 2 supports a ThreadContext which is analogous to the SLF4J MDC. Both are based on ThreadLocal variables. If I understand what you are saying, the problem is that ThreadLocals do not work as you you would expect when using CompleteableFutures?
Ralph
> On Mar 22, 2018, at 7:05 AM, Dean Hiller <dhiller at twitter.com> wrote:
>
> slf4j is pretty much the defacto logging standard these days allowing one
> to bring in libraries using any logging framework. (commons logging fell
> short and had classloading bugs).
>
> Summary: MDC works fine in twitter scala Futures but not java
> CompletableFutures.
>
> Unfortunately, one of the best features(brought over from log4j which is
> also broken now) is the MDC. The MDC no longer works with
> CompletableFutures so people will have to move to scala where it does work.
>
> Documentation on MDC if you don't know what that is....
> https://logback.qos.ch/manual/mdc.html
>
> or for a more concrete example, as a developer a request comes in and you
> set MDC.put("requestId", requestId) and now whenever you log, that request
> id is added to your log line. No developer has to 'remember' to add it
> every time he adds a log statement.
>
> This is due to the lack of Local.java file that should exist and transfer
> context over the .thenApply/.thenCompose methods like twitter Futures has
> in scala land. (see Local.scala in twitter Futures and the twitter Future
> code for how this works)
>
> In scala, it works and we have all the same methods as CompletableFuture
> for the most part and yes, we can't transfer the context over some methods,
> but at least our MDC in scala servers is not broken.
>
> Lack of this feature is forcing our hand to code in scala where it is not
> broken. ie. we need logging and we definitely need the request id or
> client id or whatever attached automatically to every log(as humans have
> trouble remembering to add it themselves every single time).
>
> thanks for reconsidering,
> Dean
>
> On Tue, May 23, 2017 at 10:20 AM, Dean Hiller <dhiller at twitter.com> wrote:
>
>> All, this post is all about 3rd party code that I do not control so
>> therefore the solutions above do not work as those libraries may predate my
>> library. more specifically.....
>>
>> Martin,
>> If I roll my own slf4j MDC only works in my code and stops working in
>> 3rd party code! because the 3rd party code does not transfer the context.
>>
>> Viktor,
>> You hit the head on the nail with "It's easy to lose context when
>> intermediate libraries/Executors". This is solved on twitter futures until
>> we hit libraries not using twitter futures because no matter the executor,
>> the future transfers the context for us the way it was written.
>>
>> "It's unclear what fan-in behaviors like zip, merge etc mean in terms
>> of what the local values should be?"
>> This is a very good question. I wonder what twitter futures do here. I
>> would be ok with dropping the context in this case or combining it. I do
>> not really care yet here since I have not run into it but it is a very good
>> question and would need a lot of thought
>>
>> Josh,
>> I cannot expect all 3rd party libraries that are brought in will be
>> using ContextPropagatingExecutor so that solution breaks down as Viktor
>> eludes to.
>>
>> Alex,
>> tuples do not solve the issue. in fact twitter futures have a
>> Local.scala file that does solve the issue. The main issue is 3rd party
>> code and having the context continue into "unknown code" using
>> CompletableFuture. I cannot control that code BUT want every log.info in
>> that code to use and log the request id. it is awesome at twitter as I can
>> just follow that request id in the logs. If CompletableFuture had such a
>> context, I could transfer this info into it and into the 3rd party java
>> libraries.
>>
>> I am writing a webserver for fun based on CompletableFutures and therefore
>> cannot control the controllers as the app developer writes that and the
>> request id stops getting logged on the request path which is mostly
>> .thenApply and .thenCompose. even if the Controllers do you my future,
>> they will bring in libraries NOT using my future :(
>>
>> thanks
>> Dean
>>
>>
>>
>>
>>
>> On Tue, May 23, 2017 at 3:12 AM, Alex Otenko <oleksandr.otenko at gmail.com>
>> wrote:
>>
>>> Why would someone want to rely on state they cannot control?
>>>
>>> Is the idea to subvert some API that does not provide a way to pass
>>> state? This is strange especially in the context of Scala, where you can
>>> easily form tuples.
>>>
>>> Alex
>>>
>>> On 22 May 2017, at 20:44, Martin Buchholz <martinrb at google.com> wrote:
>>>
>>> There's not likely to be any support for local context anywhere in
>>> java.util.concurrent, but it seems not too hard to roll your own support
>>> with a custom executor to be used with CompletableFuture that kept track of
>>> any local context.
>>>
>>> On Fri, May 19, 2017 at 1:16 PM, Pavel Rappo <pavel.rappo at oracle.com>
>>> wrote:
>>>
>>>> General questions on concurrency in Java should be asked here:
>>>>
>>>> http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>
>>>>> On 18 May 2017, at 21:57, Dean Hiller <dhiller at twitter.com> wrote:
>>>>>
>>>>> Way more detail here...
>>>>>
>>>>> http://stackoverflow.com/questions/37933713/does-completable
>>>> future-have-a-corresponding-local-context
>>>>>
>>>>> So I was wondering if this was going to be added at some point to the
>>>> jdk
>>>>> as I could not figure out how to set something so it was still
>>>> available on
>>>>> the thread at a later time when traversing async thenCompose,
>>>> thenAccept.
>>>>>
>>>>> thanks,
>>>>> Dean
>>>>
>>>>
>>> _______________________________________________
>>> Concurrency-interest mailing list
>>> Concurrency-interest at cs.oswego.edu
>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>
>>>
>>>
>>
>
More information about the core-libs-dev
mailing list