1

正如我在 akka 规范中所读到的,它支持演员中的 mdc。例如,我可以将 unic 信息放在 mdc 中,然后在 actor 中使用它。但是期货呢?akka 是否提供任何保证,即在 actor 中发起的未来将具有相同的 mdc?另外,发送给其他参与者的消息怎么样 - 默认情况下会复制 MDC 吗?

笔记

对我来说,这看起来很奇怪,我只能在一个演员代码中使用 MDC。

4

1 回答 1

4

他们可以,但实际上没有。当你调用 LoggingAdapter 的成员时,你实际上调用了 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))
  ...
}

所以你在这里访问演员的成员。每次处理请求之前都会设置此成员:

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()
  }
}

因此,如果您从未来访问它(可能与其他消息同时运行的另一个线程) - 不能保证您为您的消息选择 mdc。与接收器相同的问题,但更深,因为您无法轻松捕获额外的 mdc 信息。

PS Akka 可能更聪明,并且可以隐式获取 mdc 信息,因此您可以将其捕获为闭包,如下所示:

  implicit val metaMdc = getMetaMdc
  Future {

    log.warning(...)
  }

这里的问题是,Akka 每次登录时都必须将此 metaMdc 附加到当前线程的 mdc(或者您必须以某种方式对其进行初始化),因为 SLF4J 的 Mdc 是thread-local,因此每个线程都不同。因此,Akka 不知道您将使用哪个物理 MDC 执行您的log.warning(...).

于 2015-07-06T04:12:23.020 回答