1
votes

As I read in akka specification it supports mdc in actors. E.g. I can put unic infomation in mdc and then use it in actor. But what about futures? Does akka provide any guaranties that a future which is initiated in actor will have the same mdc? Also what about message that send to other actors - is MDC copied by default?

Note

For me it looks very strange, that I can use MDC only inside one actor code.

1

1 Answers

4
votes

They could but they actually don't. When you call members of LoggingAdapter you actually call member of actor:

package akka.event
trait LoggingAdapter {// and it's implementations DagnosticLoggingAdapter, BusLoggingAdapter

  type MDC = Logging.MDC
  def mdc = Logging.emptyMDC
  def notifyError(message: String): Unit = bus.publish(Error(logSource, logClass, message, mdc))
  ...
}

So you're accessing actor's member here. This member is set every time before processing request:

package akka.actor
trait DiagnosticActorLogging extends Actor {
  ...

  override protected[akka] def aroundReceive(receive: Actor.Receive, msg: Any): Unit = try {
    log.mdc(mdc(msg))
    super.aroundReceive(receive, msg)
  } finally {
    log.clearMDC()
  }
}

So if you're accessing it from the future (another thread which might be run simultaneously with some other message) - there is no guarantee that you pick up mdc for your message. Same problem as for receiver, but more deep as you can't capture additional mdc info easy way.

P.S. Akka could be smarter and acquire mdc information as implicit, so you could capture it as a closure, something like that:

  implicit val metaMdc = getMetaMdc
  Future {

    log.warning(...)
  }

The problem here is that Akka would have to attach this metaMdc to current thread's mdc every time you log (or you have to initialize it some way) as SLF4J's Mdc is thread-local, so it's different for every thread. So, Akka doesn't know with which exactly physical MDC you're gonna execute your log.warning(...).