1
我想使用log4j2
異步日誌記錄將線程ID作爲日誌消息的一部分進行記錄。在log4j2中傳遞threadId的最佳方法AsyncLogger
With log4j2
2.4.1這可以通過覆蓋logMessage方法的自定義AsyncLogger
來實現。
public class ThreadIdAsyncLogger extends AsyncLogger {
private static final long serialVersionUID = 1L;
private static final ThreadLocal<Boolean> THREAD_CONTEXT_SETUP = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return false;
}
};
public ThreadIdAsyncLogger(final LoggerContext context, final String name, final MessageFactory messageFactory) {
super(context, name, messageFactory);
}
@Override
public void logMessage(final String fqcn,
final Level level,
final Marker marker,
final Message message,
final Throwable thrown) {
if (!THREAD_CONTEXT_SETUP.get()) {
// it is enough to set it once per thread
ThreadContext.put(Constants.ContextMapKeys.THREAD_ID, String.valueOf(Thread.currentThread().getId()));
THREAD_CONTEXT_SETUP.set(true);
}
super.logMessage(fqcn, level, marker, message, thrown);
}
}
我只是想更新到2.5.0版本,現在我不似乎能夠創建自己的AsyncLogger
了,因爲AsyncLoggerDisruptor
是包專用。 我知道我可以使用反射,但我想有一個更好的方法。
實現相同功能的最佳實踐(設計和性能明智)是什麼?
在代碼中的哪個位置應該將threadId壓入堆棧?我想在記錄器中一次性完成此操作,而不是在應用程序代碼中的每個記錄器調用之前執行此操作。你在這裏建議什麼?我應該等待(保持在2.4.1),直到你提到的門票被解除了嗎? – leozilla
通常只有一個入口點,您的應用程序從提供線程模型的框架接收回調。如果您的應用程序是線程池中的某些任務,那將是Runnable的run()方法或Callable的call()方法。對於Servlet,它是service()或doXxx()方法之一。其他框架還有其他回調函數,但通常這些入口點將是推送線程ID的理想候選者(並且在代碼完成後將其彈出)。 –
好吧,我明白了。不幸的是,我只能爲我控制的代碼而不是一些「中間件」線程執行此操作。看着log4j異步記錄器代碼,無論如何,我看到你已經需要獲得threadid,如果你有它,也許可以將它與LogEvent一起傳遞。 – leozilla