Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

logging

akka

mdc

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 /:

like image 220
kumetix Avatar asked May 03 '15 15:05

kumetix


2 Answers

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>
like image 99
Yura Lazarev Avatar answered Sep 28 '22 06:09

Yura Lazarev


You could set up your non-akka loggers to use the same style of MDC. It's not very complicated and you can look at Akka's Slf4jLogger class to see how it is done.

For the current thread you can simply use Thread.currentThread.getName and for the time (in order to be 1:1 with the Akka impl) you can have a look at the Helpers.currentTimeMillisToUTCString method in Akka (see here for currentTimeMillisToUTCString)

Happy hakking!

like image 22
Konrad 'ktoso' Malawski Avatar answered Sep 28 '22 06:09

Konrad 'ktoso' Malawski