如何在非 Akka 部件调度的日志事件中提供可用的 sourceThread 和 akkaTimestamp 值?
How to make available sourceThread and akkaTimestamp values in log events dispatched by non-Akka parts?
我们的 Akka 项目依赖于其他一些非 akka 代码。在此代码中,我们获取记录器的方法是调用 org.slf4j.LoggerFactory.getLogger(ThisClass.class)
我希望在日志打印中包含事件发生的时间和地点的 真实 时间和 真实 线程,所以我获取 akkaTimestamp 和 sourceThread 的值,如下所示:
log4j.appender.console.layout.ConversionPattern=[%-5p] [%X{akkaTimestamp}] [%X{sourceThread}] %c{5}: %m%n
问题是从 MDC 中提取的这些值在从非 akka 记录器发送的打印中不可用。
Here 他们说
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.
但他们从不说如何/:
您可以将非 akka 记录器设置为使用相同样式的 MDC。
它不是很复杂,你可以看看 Akka 的 Slf4jLogger class 看看它是如何完成的。
对于当前线程,您可以简单地使用 Thread.currentThread.getName
,暂时(为了使用 Akka 实现 1:1),您可以查看 Helpers.currentTimeMillisToUTCString
方法在 Akka 中(currentTimeMillisToUTCString 见此处)
Hakking 快乐!
正如 Konrad 所说,它并没有那么复杂。这对我有用:
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)
}
}
}
然后在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>
我们的 Akka 项目依赖于其他一些非 akka 代码。在此代码中,我们获取记录器的方法是调用 org.slf4j.LoggerFactory.getLogger(ThisClass.class)
我希望在日志打印中包含事件发生的时间和地点的 真实 时间和 真实 线程,所以我获取 akkaTimestamp 和 sourceThread 的值,如下所示:
log4j.appender.console.layout.ConversionPattern=[%-5p] [%X{akkaTimestamp}] [%X{sourceThread}] %c{5}: %m%n
问题是从 MDC 中提取的这些值在从非 akka 记录器发送的打印中不可用。
Here 他们说
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.
但他们从不说如何/:
您可以将非 akka 记录器设置为使用相同样式的 MDC。 它不是很复杂,你可以看看 Akka 的 Slf4jLogger class 看看它是如何完成的。
对于当前线程,您可以简单地使用 Thread.currentThread.getName
,暂时(为了使用 Akka 实现 1:1),您可以查看 Helpers.currentTimeMillisToUTCString
方法在 Akka 中(currentTimeMillisToUTCString 见此处)
Hakking 快乐!
正如 Konrad 所说,它并没有那么复杂。这对我有用:
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)
}
}
}
然后在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>