Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在log4j2异步记录器中传递threadId的最佳方法_Java_Asynchronous_Logging_Log4j_Log4j2 - Fatal编程技术网

Java 在log4j2异步记录器中传递threadId的最佳方法

Java 在log4j2异步记录器中传递threadId的最佳方法,java,asynchronous,logging,log4j,log4j2,Java,Asynchronous,Logging,Log4j,Log4j2,我想使用log4j2Async日志记录将线程Id记录为日志消息的一部分 使用log4j22.4.1,可以通过覆盖logMessage方法的自定义AsyncLogger实现这一点 public class ThreadIdAsyncLogger extends AsyncLogger { private static final long serialVersionUID = 1L; private static final ThreadLocal<Boolean>

我想使用
log4j2
Async日志记录将线程Id记录为日志消息的一部分

使用
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);
    }
}
公共类ThreadIdAsyncLogger扩展了AsyncLogger{
私有静态最终长serialVersionUID=1L;
私有静态最终线程本地线程\u上下文\u设置=新线程本地(){
@凌驾
受保护的布尔初始值(){
返回false;
}
};
公共线程IDASyncLogger(最终LoggerContext上下文、最终字符串名称、最终MessageFactory MessageFactory){
super(上下文、名称、消息工厂);
}
@凌驾
公共无效日志消息(最终字符串fqcn,
最后一级,
最终标记,
最后的信息,
最后一次投掷){
如果(!THREAD\u CONTEXT\u SETUP.get()){
//每个线程设置一次就足够了
ThreadContext.put(Constants.ContextMapKeys.THREAD_ID,String.valueOf(THREAD.currentThread().getId());
THREAD_CONTEXT_SETUP.set(真);
}
super.logMessage(fqcn、级别、标记、消息、抛出);
}
}
我刚刚尝试更新到2.5.0版,现在我似乎无法再创建自己的
AsyncLogger
,因为
AsyncLoggerDisruptor
是包私有的。 我知道我可以使用反射,但我想有更好的方法


实现相同功能的最佳实践(设计和性能方面)是什么?

这方面的工作正在进行中:


同时,您可以使用ThreadLocal映射或堆栈方法来实现这一点。就性能而言,ThreadLocal堆栈比我认为的map稍微便宜一些

我应该在代码中的哪个位置将threadId推送到堆栈上?我想在logger中一次性执行此操作,而不是在每次logger调用应用程序代码之前。你有什么建议?我应该等待(停留在2.4.1)直到您提到的问题得到解决吗?通常有一个入口点,您的应用程序从提供线程模型的框架接收回调。如果应用程序是线程池中的某些任务,则可能是Runnable的run()方法或Callable的call()方法。对于servlet,它是service()或doXxx()方法之一。其他框架有其他回调,但一般来说,这些入口点将是推送线程ID(并在代码完成后弹出)的理想候选。不幸的是,我只能对我控制的代码这样做,而不能对某些“中间件”线程这样做。查看log4j异步记录器代码,我发现您已经需要获取threadid了,如果您已经获得了它,那么可以将它与LogEvent一起传递。我会考虑一些解决方案..嗯,再看看AsyncLogger和RingBufferLogEventTranslator的代码,如果我使用的是非缓存线程名称策略@AsyncLogger#initTranslatorThreadValues,那么threadId应该已经在LogEvent上了。你正在查看GitHub中的主分支?这将在即将发布的2.6版中发布。