簡體   English   中英

Scala Akka使用SLF4J MDC進行記錄

[英]Scala Akka Logging with SLF4J MDC

我正在配置我的Akka應用程序以使用此處指定的SLF4J記錄器:

http://doc.akka.io/docs/akka/2.3.4/scala/logging.html

在引擎蓋下,我依靠Logback進行日志記錄。 我正在開發一個用於日志記錄目的的通用模塊,用戶可以在他們的actor系統中使用。 主要是,我正在創造一個他們可以混合的特質。

我有一個特點,這樣做:

我有這樣的東西:

trait ActorLogger {

    val log: DiagnosticLoggingAdapter = Logging(this);

}

我有一些額外的邏輯,它將MDC值添加到DiagnosticLoggingAdapter的MDC。 現在的問題是:如果用戶想要混合到非演員類,我會完全暴露一個不同的記錄器。 所以我可能有這樣的事情:

trait ClassLogger {

    val log = LoggerFactory getLogger getClass.getName
}

我希望MDC值能夠延續到此記錄器。 因此,例如,如果我將MDC值放入我的DiagnosticAdapterLogger,我應該能夠從org.slf4j.MDC獲取這些值

如何以干凈的方式實現這一目標?

謝謝!

如果actor系統之外的所有代碼都是單線程的(即你沒有產生任何額外的期貨或線程),那么有一個比@jasop引用更簡單的解決方案。

我有這個mixin負責在演員內部和外部填充MDC:

import akka.actor.DiagnosticActorLogging
import akka.contrib.pattern.ReceivePipeline
import org.slf4j.MDC
import scala.collection.JavaConverters.mapAsJavaMapConverter

trait MdcActorLogging extends DiagnosticActorLogging {
  this: ReceivePipeline =>

  /**
    * This is for logging in Akka actors.
    */
  override def mdc(message: Any): akka.event.Logging.MDC = {
    message match {
      case MyMessage(requestId) => Map("requestId" -> requestId)
      case _ => Map()
    }
  }

  /**
    * This makes the MDC accessible for logging outside of Akka actors by wrapping the actor's
    * `receive` method.
    * Implements the [[http://doc.akka.io/docs/akka/2.4/contrib/receive-pipeline.html ReceivePipeline]]
    * pattern.
    */
  pipelineOuter {
    case e @ MyMessage(requestId) =>
      val origContext = MDC.getCopyOfContextMap
      val mdcWithPath = Map("requestId" -> requestId,
        // inside actors this is already provided, but outside we have to add this manually
        "akkaSource" -> self.path.toString)
      MDC.setContextMap(mdcWithPath.asJava)
      ReceivePipeline.Inner(evt) // invoke actual actor logic
        .andAfter {
          if (origContext != null)
            MDC.setContextMap(origContext)
          else
            MDC.clear()
        }
    case e => ReceivePipeline.Inner(e) // pass through
  }
}

com.typesafe.scalalogging.LazyLogging代碼可以使用任何記錄器,例如com.typesafe.scalalogging.LazyLogging特征中的混合。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM