Using SLF4J MDC across threads

Mapped diagnostic context (MDC) is a tool that allows propagating diagnostic information from method to method without cluttering methods' signatures with excessive parameters. Semantically, this information is task-scoped, i.e., it is relevant only to a specific task, and may be added to log entries by a logging library without writing additional application code.

SLF4J, Logback, Log4j 2 all implement MDC by making its state thread-scoped. This means that the information is accessible to the code that is executed by the same thread and is not accessible to the code executed by different threads. This approach works fine when a single task is processed by a single thread and fails if more than one thread participates in processing a task. Logback recommends using the methods MDC.getCopyOfContextMap()/MDC.setContextMap(Map<String, String> contextMap) for transferring the context between threads, Log4j 2 also suggests implementing such transferring in the application. In my opinion, this task should be solved by logging libraries instead of being shifted to users, especially given that if a user forgets to roll back thread's context changes after the thread finished working on a task, then log entries related to other tasks may be polluted with the data from the transferred context because threads may and should be reused for other tasks. So I created this pull request implementing the aforementioned functionality in SLF4J. The API can be used like this:

TransferableMdc outerMdc = TransferableMdc.current();
executor.submit(() -> {
  try (var transferredMdc = outerMdc.transfer()) {
    logger.info("This call can access contents of outerMdc via org.slf4j.MDC");
  }
  logger.info("This call cannot access contents of outerMdc via org.slf4j.MDC");
});

This pull request was not merged into SLF4J because we could not come to an agreement with Ceki Gulcu, its author, about the behavior of the TransferableMdc.close() method: he thinks this method should always clear MDC, while I think it should roll back the changes by reverting the context state to the state before MDC was transferred. As a side note, I think that merge/unmerge behavior may be implemented additionally as an alternative to the current override/rollback behavior, as I mentioned in this comment, but always clearing the context seems more like a disruptive rather than helping behavior.

Anyway, the class TransferableMdc is documented, tested and you are free to use it, as it is licensed under WTFPL.