当前位置: 首页 > 知识库问答 >
问题:

Log4J2 appender未记录到ThreadContext文件夹

太叔栋
2023-03-14

我有下面的Log4J2配置XML:

<Routing name="myAppender">
    <Routes pattern="$${ctx:workId}">
        <Route>
            <File fileName="${my-path}/sites/${ctx:workId}/${date:yyyy-MM-dd}/${ctx:employeeId}/emp.log" name="myAppender-${ctx:workId}">
                <MarkerFilter marker="TELEMETRIC" onMatch="ACCEPT" onMismatch="DENY"/>
                <PatternLayout>
                    <Pattern>[%date{ISO8601}][%-5level][%logger{1.}][%marker][$${ctx:employeeId}] %X%m%n</Pattern>
                </PatternLayout>
            </File>
        </Route>
    </Routes>
</Routing>

<Async name="Async">     
    <AppenderRef ref="myAppender" level="info"/>
</Async>

但是,每当log4j2 appender写入文件时,它在写入指定的文件路径时不会使用正确的${ctx:employeeId}字符串。

log4j2 appender第一次写入文件时,会写入由${ctx:employeeId}指定的正确文件路径。但是,只要将具有另一个Id的员工的信息放入线程上下文中,appender仍然会记录到旧文件路径。

例如,appender第一次记录时,它会写入正确的路径:

D:/example/logs/sites/1/2015-08-22/2/emp.log

但当记录器记录下一个员工Id(使用新的ThreadContext)时,它仍在登录

D:/example/logs/sites/1/2015-08-22/2/emp.log

例如:

D:/example/logs/sites/1/2015-08-22/3/emp.log

(请注意,员工Id不同。)

在日志输出模式中,我记录当前的雇员ID[$${ctx:雇员ID}],以及当前线程上下文%X中的内容。输出显示正在使用正确的雇员ID,并且位于ThreadContext中,但是附加程序没有记录到该${ctx:雇员ID}文件路径。

有人知道我是否遗漏了什么吗?或者如果我做错了什么?或者这可能是Log4j2的一个bug?谢谢你的帮助!

共有1个答案

终彬郁
2023-03-14

好吧,我意识到这个答案是在问题被问了很久之后才给出的,但如果这仍然对你或其他人有帮助,我将分享我的发现。

首先,我不能重现这个问题,但我有代码可以实现您想要的,所以我将分享我的代码,希望通过查看它,您可以确定哪里出了问题。如果没有,请提供一个最小的、完整的、可验证的示例,以便任何试图帮助您的人都可以重现该问题。

这是我的工作代码:

package pkg;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import org.apache.logging.log4j.ThreadContext;

public class Log4j2DiffFilePerCtxVarMain {
    private static final Marker TELEMETRIC = MarkerManager.getMarker("TELEMETRIC");

    public static void main(String[] args){
        Logger log = LogManager.getLogger();

        ThreadContext.put("workId", "mainWorkId");
        ThreadContext.put("employeeId", "mainEmployeeId");

        log.info(TELEMETRIC, "Hey here's some info log from main!");

        Thread t1 = new Thread(new Runnable(){
            public void run(){
                Logger log = LogManager.getLogger();
                ThreadContext.put("workId", "thread1WorkId");
                ThreadContext.put("employeeId", "thread1EmployeeId");

                log.info(TELEMETRIC, "Hey here's some info log from thread1!");
            }
        });
        t1.start();
    }
}

以下是log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Routing name="myAppender">
            <Routes pattern="$${ctx:workId}">
                <Route>
                    <File
                        fileName="logs/${ctx:workId}/${date:yyyy-MM-dd}/${ctx:employeeId}/emp.log"
                        name="myAppender-${ctx:workId}">
                        <MarkerFilter marker="TELEMETRIC" onMatch="ACCEPT"
                            onMismatch="DENY" />
                        <PatternLayout>
                            <Pattern>[%date{ISO8601}][%-5level][%logger{1.}][%marker][$${ctx:employeeId}] %X %m%n</Pattern>
                        </PatternLayout>
                    </File>
                </Route>
            </Routes>
        </Routing>

        <Async name="Async">
            <AppenderRef ref="myAppender" level="info" />
        </Async>
    </Appenders>
    <Loggers>
        <Root level="trace">
            <appender-ref ref="Async" />
        </Root>
    </Loggers>
</Configuration>

当我用这个log4j2运行代码时。xml我看到了以下结果:

第一个日志包含以下内容:

[2017-04-13T20:42:49,814][INFO ][p.Log4j2DiffFilePerCtxVarMain][TELEMETRIC][mainEmployeeId] {employeeId=mainEmployeeId, workId=mainWorkId} Hey here's some info log from main!

第二个日志包含以下内容:

[2017-04-13T20:42:49,822][INFO ][p.Log4j2DiffFilePerCtxVarMain$1][TELEMETRIC][thread1EmployeeId] {employeeId=thread1EmployeeId, workId=thread1WorkId} Hey here's some info log from thread1!

希望这有帮助!

 类似资料:
  • 我在dropwizard yml文件中配置了日志记录以记录到文件而不是控制台,但是一些日志仍在记录到控制台。 service.yml 当我执行时,我在日志文件中获取服务日志,但我在控制台上而不是日志文件中获取请求日志 我正在使用滴滴巫师 0.7.1

  • 问题内容: 我需要将对项目中的Oracle数据库的所有查询记录到日志文件中。 有什么 好的 解决方案来实现这一目标?一些示例用法将不胜感激。 我已经用jdbcdslog查看了SLF4J,但不确定如何使用它登录到文件。而且,我需要“过滤”一些日志(因为我不需要知道何时调用某种方法) 最好是,我更愿意使用,但这不是必需的。 谢谢。 更新 我找到了这篇Oracle文章,但是它并没有真正告诉您如何以编程方

  • 问题内容: 我从golang开始,随着我开始建立自己的应用程序,我想从一开始就添加日志记录,这就是我遇到问题的地方。 如果我打开文件并使用标准日志记录库,则可以写入文件。像这样 我将获得带有日志行的test.log。但是,如果我尝试调整它以支持logrus https://github.com/Sirupsen/logrus这样 我只会看到错误。 写入日志失败,写入testlogrus.log:文

  • 问题内容: 有没有一种方法可以将log4j日志事件写入到也由其他应用程序写入的日志文件中。其他应用程序可以是非Java应用程序。有什么缺点?锁定问题?格式化? 问题答案: Log4j有一个SocketAppender,它将事件发送到服务,您可以自己实现或使用与Log4j捆绑在一起的简单实现。 它还支持syslogd和Windows事件日志,这对于尝试将日志输出与非Java应用程序中的事件统一起来可

  • 运行时,我收到以下消息: 我已经把位于下(但不在中,因为我不希望它随实际应用程序一起提供),如这里所建议的那样没有任何效果。 生成超文本标记语言报告,编写日志文件,构建成功,如上所述。我不确定错误是从哪里来的。

  • 问题内容: 我有一个dropwizard应用程序,在该应用程序中,我配置了logger附加程序,使其文件如下: 并且,在我的应用中创建了记录器: 在main()中进行一些测试记录: 该应用程序启动并运行没有问题。但是我没有在stdout或mylogs.log文件中得到任何日志(当然,除了Jetty访问日志之外,这些日志也已正确打印到mylogs.log中)。相反,如果我删除configuratio