正如我在 akka 规范中所读到的,它支持演员中的 mdc。例如,我可以将 unic 信息放在 mdc 中,然后在 actor 中使用它。但是期货呢?akka 是否提供任何保证,即在 actor 中发起的未来将具有相同的 mdc?另外,发送给其他参与者的消息怎么样 - 默认情况下会复制 MDC 吗?
笔记
对我来说,这看起来很奇怪,我只能在一个演员代码中使用 MDC。
他们可以,但实际上没有。当你调用 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(...)
.