kotlinx.coroutines icon indicating copy to clipboard operation
kotlinx.coroutines copied to clipboard

Add an integration with Log4J 2's ThreadContext

Open MariusVolkhart opened this issue 5 years ago • 5 comments

Log4J 2 has a ThreadContext, which works the same way as SLF4J's MDC. Using the ThreadContext directly with coroutines breaks, but the same approach for an integration that exists for SLF4J can be used for Log4J.

The tests are copied from the SLF4J project, and are only modified to also include verification of stack state, since ThreadContext contains both a Map and a Stack.

MariusVolkhart avatar Feb 10 '20 22:02 MariusVolkhart

@elizarov Thank you very much for the feedback. I feel I gained a much better understanding of coroutines from it, and appreciate you taking the time to leave it.

I've applied the changes you suggested, and will summarize them below.

  • Dropped support for the logging context stack. It now only supports the Map. Conversations from the Log4J 2 maintainers suggested that using the stack is not really encouraged. This matches the behavior I've seen in other applications.
  • Renamed Log4JThreadContext -> DiagnosticContext as I think it is unlikely for developers to have multiple conflicting classes of the same name, and I wanted to get away from thinking about threads.
  • Added the MutableDiagnosticContext type, for cases when the state for the duration of the coroutine context should be modified. The API for this matches closely with that of Log4J's CloseableThreadContext, which rolls-back the state when close() is called.
  • Added the immutableDiagnosticContext() function to create an optimized instance of DiagnosticContext for cases when the state should be captured when the coroutine context starts, but will not be modified.

MariusVolkhart avatar Apr 18 '20 18:04 MariusVolkhart

@MariusVolkhart Any updates on this integration?

t1mwillis avatar Oct 23 '20 22:10 t1mwillis

@t1mwillis What sort of an update are you looking for? I believe this code to be working, but I've only had limited ability to deploy it into production.

@elizarov would you please take another look at this?

MariusVolkhart avatar Oct 24 '20 11:10 MariusVolkhart

@t1mwillis It has recently occurred to me that it may be possible to implement the ThreadContextMap interface in such a way that the CoroutineContext is used as the storage container, rather than a ThreadLocal map as is used by the default ThreadContextMap subclasses. The API would probably look pretty similar, but there would likely be one round of copying things from the CoroutineContext to theThreadLocal and back saved.

I haven't had the chance to investigate this yet.

MariusVolkhart avatar Nov 11 '20 19:11 MariusVolkhart

@MariusVolkhart my use case was simply having a structured way to write a tracking id from the parent thread to a coroutine. At present I am grabbing this tracking id from the parent thread and then setting it in the coroutine using threadContext.put('trackingid', parentThreadTrackingId). This works but seems unnecessary

t1mwillis avatar Nov 12 '20 00:11 t1mwillis