Search code examples
loggingakkamdc

How to make available sourceThread and akkaTimestamp values in log events dispatched by non-Akka parts?


Our Akka project depends on some other non akka code. From within this code our way to get a logger is by calling org.slf4j.LoggerFactory.getLogger(ThisClass.class)

I would like to have the real time and real thread when and where the event took place, included in the log print, so I fetch the values of akkaTimestamp and sourceThread, as following:

log4j.appender.console.layout.ConversionPattern=[%-5p] [%X{akkaTimestamp}] [%X{sourceThread}] %c{5}: %m%n

Problem is that these values, which are extracted from the MDC, are not available in the prints which were dispatched from the non-akka loggers.

Here they say

It will probably be a good idea to use the sourceThread MDC value also in non-Akka parts of the application in order to have this property consistently available in the logs.

But they never say how /:


Solution

  • As Konrad says, its not that complicated. This is what worked for me:

    import akka.util.Helpers
    import ch.qos.logback.core.ConsoleAppender
    import org.slf4j.MDC
    
    /**
     * Decorates MDC with same keys as Akka in
     * <a href="https://github.com/akka/akka/blob/master/akka-slf4j/src/main/scala/akka/event/slf4j/Slf4jLogger.scala#L89">Slf4jLogger</a>
     * So that logging messages dispatched from non-akka threads has same data.
     */
    class AkkaCompatibleConsoleAppender[E] extends ConsoleAppender[E] {
    
      val mdcThreadAttributeName = "sourceThread"
      val mdcAkkaTimestamp = "akkaTimestamp"
    
      override def append(eventObject: E): Unit = {
        try {
          MDC.put(mdcAkkaTimestamp, Helpers.currentTimeMillisToUTCString(System.currentTimeMillis()))
          MDC.put(mdcThreadAttributeName, Thread.currentThread().getName)
          super.append(eventObject)
        } finally {
          MDC.remove(mdcAkkaTimestamp)
          MDC.remove(mdcThreadAttributeName)
        }
      }
    }
    

    And then in logback.xml:

    <appender name="STDOUT" class="agordo.server.AkkaCompatibleConsoleAppender">
        <encoder>
            <pattern>%X{akkaTimestamp} %-5level %logger{36} %X{sourceThread} %X{akkaSource} - %msg%n</pattern>           
        </encoder>
    </appender>