Scala Akka Logging with SLF4J MDC

后端 未结 1 1138
生来不讨喜
生来不讨喜 2020-12-16 05:54

I\'m configuring my Akka application to use the SLF4J logger as specified here:

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

Underneath the hood, I\

相关标签:
1条回答
  • 2020-12-16 06:13

    If all your code outside the actor system is single-threaded (i.e. you don't spawn any additional futures or threads), there's a simpler solution than the one @jasop references.

    I have this mixin that takes care of populating the MDC both inside and outside actors:

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

    The non-actor code can use any logger, e.g. mix in the com.typesafe.scalalogging.LazyLogging trait.

    0 讨论(0)
提交回复
热议问题