In our system, our loggers rely on MDC to pass information around. That's fine as long as you don't have use-cases with logic spilling across threads, but unfortunately that's the reality of modern software development.
I came up with the following solution that we could hopefully use as a wrapper around our global threadpool (the Logger / MDC methods are fictitious and only for illustrative purposes):
class MDCAwareExecutionContext(ec: ExecutionContext) extends ExecutionContext {
override def execute(runnable: Runnable): Unit = {
val mdc: java.util.Map[_, _] = Logger.getMDCValues()
ec.execute(() =>
Logger.clearMDCValues()
Logger.setMDCValues(mdc)
runnable.run()
)
}
override def reportFailure(cause: Throwable): Unit =
ec.reportFailure(cause)
}
But my colleague referred that he in the past tried something similar and that through empirical experience it did not work. He suggested an alternative, instead, based on ExecutionContext.prepare(), that's declared as deprecated. I have no reason to think he's wrong, but on the other hand I fail to understand what may go awry in my example.
Is there some reason why this would not work as intended in Scala? I would assume that outside of the future we're still in position to correctly capture the MDC and that inside the future we're already in an arbitrary thread, but always safe to read the originalMdc variable. Am I missing some obscure possibility?