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\
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.