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

以编程方式更改Log4j2 RollingFileAppender在运行时写入的文件名

桑鸿志
2023-03-14

我的组织正在从Log4j1迁移到Log4j2。我们有一个自定义的滚动文件追加器,当应用程序中发生某个事件时,它会在运行时更改它记录到的文件名。这是为了便于在日志目录中查找日志文件而实现的。例如,日志文件目录可能如下所示;

mylog-2021-08-02。日志

mylog-2021-08-03.log

特殊事件(mylog-2021-08-03)。日志

mylog-2021-08-04.log

mylog-2021-08-05。日志

根据我所做的研究,Appender文件名似乎是不可变的,我必须创建一个新的Appender,并在事件发生时将其添加到配置中,然后在触发策略发出信号时删除此Appender,并为原始配置重新添加一个新的Appender?有比这更优雅的解决方案吗?我是否需要自己编写一个自定义附加器并处理文件命名/滚动逻辑?

更新日期:9/2/2021

感谢@D.B.的回答。这帮助我了解了很多关于Log4j2的知识。你提到的问题与我的情况非常相似。我们有很多设备,每个设备都需要登录到自己的文件。不过我还有一些额外的要求。我们在每个设备中都有许多线程需要登录到同一个设备日志文件,并且许多设备都需要自己的日志文件。此外,当设备中发生特定事件时,我需要处理特殊的滚动文件命名要求(原始post)。最后,分配给每个设备的名称在运行时之前是未知的(它在我们的另一个配置文件中定义)。我可以像您建议的那样使用标记,但这很快就会变得难以维护,因为开发人员需要知道他们必须在每个日志语句中传递一个标记,并且需要更新整个现有代码库以传递适当的标记。我也可以按照您的建议使用上下文映射,但是应用程序有许多线程,开发人员需要知道,在从任何线程登录之前,他们必须正确设置上下文数据。

对于Log4j1,这些要求通过以下方式得到满足:

  1. 从处理特殊事件文件命名滚动逻辑的RollingFileAppender派生的自定义appender类
  2. 接受符合以下条件的事件的自定义筛选器:A.事件的线程名称来自设备的“设备名称”。b.事件消息包括“设备名称”
  3. 在系统中实例化新设备时:a.使用“设备名称”字符串创建一个新的自定义筛选器以进行筛选。b、 将创建一个新的自定义追加器,该追加器将记录到名为“设备名称”的文件中。日志此追加器是使用自定义筛选器创建的。c、 追加器作为对根记录器的引用添加
  4. 这将导致所有日志事件被发送到新的appender(以及创建的所有其他设备appender),但日志事件将根据“设备名称”进行筛选。这将生成特定于设备的日志文件

我可以像使用Log4j1一样实现自定义过滤器和appender,但我不希望依赖于日志核心类。如果您有任何其他建议,我们将不胜感激。

共有2个答案

叶英哲
2023-03-14

您可以通过使用ThreadContext来实现它。我的配置文件如下

<Routes pattern="$${ctx:logName}">
    <Route>
        <RollingRandomAccessFile name="Rolling-Random-Access-File-Appender" fileName="${ctx:logName}.log" filePattern="${ctx:logName}.log.%d{yyyy-MM-dd-hh-mm-ss}.gz">
            <PatternLayout pattern="%msg %n"/>
            <Policies>
            <SizeBasedTriggeringPolicy size="50 MB"/>
            </Policies>
        </RollingRandomAccessFile>
    </Route>
</Routes>

在你写日志的地方放一些线程上下文,比如下面

ThreadContext.put("logName", fileName);
log4j2logger.log(level, logMessage);
吴胜
2023-03-14

在您的情况下,过滤器可能有很好的用途。因此,您将创建一个带有自定义过滤器的新文件附录,以便只包含您感兴趣的日志语句。这个附件上的文件名将是特殊情况下的文件名。

但我不认为这会让您的日志记录体验变得更容易。

我会像往常一样保持日志条目在文件中的流动,并研究如何在使用grep或其他日志聚合器之后过滤掉它们。

过滤器文档:

https://logging.apache.org/log4j/2.x/manual/filters.html

 类似资料:
  • 这里有个简单的问题。我有一个UIButton,currencySelector,我想通过编程更改文本。以下是我所拥有的: Xcode给了我一个错误“预期声明”。我做错了什么?我该如何更改按钮的文本?

  • 在Java中,我动态地创建一组文件,我希望在Linux/UNIX文件系统中更改这些文件的文件权限。我希望能够执行的Java等价物。这可能是Java5吗?如果是,怎么做? 我知道在Java6中,对象有/方法。我也知道我可以通过一个系统调用来实现这一点,但如果可能的话,我希望避免这样做。

  • 问题内容: 在Java中,我正在动态创建一组文件,并且想更改文件系统上这些文件的文件许可权。我希望能够执行的Java等效项。那可能是Java 5吗?如果是这样,怎么办? 我知道在对象具有方法。我也知道我可以进行系统调用来做到这一点,但是如果可能的话,我想避免这种情况。 问题答案: 作为“新” New IO工具(NIO.2)的一部分,Java 7中提供了对文件属性的完全控制。例如,POSIX权限可以

  • 我使用下面的hack以编程方式更改homeAsupIndicator。 但这在大多数新手机(HTC One、Galaxy S3等)上都不起作用。是否有一种方法可以跨设备统一更改。我只需要在主屏幕上更改它。其他屏幕将具有默认屏幕。因此无法使用样式。xml

  • 第一次在堆栈溢出上摆姿势,所以请原谅任何遗漏的约定。让我知道,我会补救的。 我在以编程方式运行模型时遇到问题。我认为这是因为imageio无法读取jar或外部项目中的图像文件,我无法找到修复它的方法。 当我运行模型时,一切正常,但当我从另一个项目以编程方式运行它时,我得到: 首先是警告: 然后GUI启动,当我按下“开始运行”或“初始化运行”时,我得到: 接着是我在阅读repast sourcefo

  • 问题内容: 这里的简单问题。我有一个UIButton,currencySelector,并且我想以编程方式更改文本。这是我所拥有的: Xcode给我错误“期望的声明”。我在做什么错,如何更改按钮的文本? 问题答案: 在Swift 3、4、5中: 除此以外: 还必须为声明。