【问题标题】:How to delay log file creation until Appender fileName is set programmatically for log4j2如何延迟日志文件的创建,直到以编程方式为 log4j2 设置 Appender 文件名
【发布时间】:2022-01-19 21:13:06
【问题描述】:

我有一个在 xml 中定义了 log4j 属性的项目。

<?xml version="1.0" encoding="UTF-8" ?>
    <Configuration>
        <Appenders>
            <File name="LogFileAppender" fileName="${sys:logFileName:-default}" append="false">
                <PatternLayout>
                    <Pattern>%d [%t] %p - %m%n</Pattern>
                </PatternLayout>
            </File>
        </Appenders>
    
        <Loggers>
            <Root level="error">
                <AppenderRef ref="LogFileAppender"/>
            </Root>
        </Loggers>
    </Configuration>

在发生任何日志记录以获取正确的输出文件夹之前,我将 fileName 值更新为代码中的正确路径。

public static void initializeLoggers(String logPath)
{
    // set output paths for log files
    System.setProperty("logFileName", logPath + "PROJECT.log");

    // reconfigure loggers with paths
    org.apache.logging.log4j.core.LoggerContext ctx =
            (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
    ctx.reconfigure();
}

在大多数情况下,一切都按预期进行。日志文件输出到正确的 logPath 并写出数据。但是,在我们到达 initializeLoggers() 之前,在默认项目目录中创建了一个名为“default”的文件,因为调用

static Logger log = LogManager.getLogger(MyClass.class); // Logging

在代码的顶部。

我发现不生成“默认文件”,只需将字段留空,如下所示:

fileName="${sys:logFileName:-}"

但是这样做代码会抱怨并给出错误,因为该属性在特定时间为空。

2022-01-19 13:07:51,936 main ERROR 参数为空:fileName 2022-01-19 13:07:51,944 主要错误无法创建类型的插件 类 org.apache.logging.log4j.core.appender.FileAppender 元素 文件 org.apache.logging.log4j.core.config.ConfigurationException: 为元素 File 提供的参数无效:字段 'fileName' 具有 无效值 '' 在 org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.injectFields(PluginBuilder.java:210)

有什么办法可以解决这个问题

  • 不生成未使用的“默认文件”
  • 不会引发有关空值的错误

【问题讨论】:

    标签: java xml log4j log4j2


    【解决方案1】:

    如果要延迟Log4j的初始化,需要谨慎控制LogManager.getLogger等类似方法的使用。例如,您不应在 ma​​in 类中使用静态 Logger 字段,而应仅在初始化日志记录之后调用 LogManager.getLogger

    这可能有点棘手,但系统属性 log4j2.loggerContextStacktraceOnStart 可以帮助您。

    一种更简单的方法是将配置文件移到自动配置过程之外,例如通过调用它myapp-log4j2.xml。这样第一个配置将使用默认配置(仅使用控制台附加程序),您可以在设置适当的系统变量后重新配置它:

      private static final String CONFIG_FILE = "myapp-log4j2.xml";
    
      public static void initializeLoggers(String logPath) {
        final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
        final ClassLoader cl = SomeClass.class.getClassLoader();
        final URL resource = tccl != null ? tccl.getResource(CONFIG_FILE)
            : cl != null ? cl.getResource(CONFIG_FILE) : ClassLoader.getSystemResource(CONFIG_FILE);
        if (resource != null) {
          System.setProperty("logFileName", logPath + "PROJECT.log");
          Configurator.reconfigure(resource.toURI());
        }
      }
    

    【讨论】:

    • 谢谢,这更有意义!旁注,但我怎样才能将 myapp-log4j2.xml 放入目录中?目前它需要位于项目级别,但如果我尝试设置CONFIG_FILE = "config\\myapp-log4j.xml",代码不会检测到它。我以前从未使用过 ClassLoaders 或 URL
    • 请注意,我将您的代码修改为 ClassLoader cl = MyClass.class.getClassLoader();,因为无法从静态方法引用 getClass
    • 谢谢,我相应地修改了我的答案。
    • 您知道在 cmets 中回答我的第一个问题的方法吗?如果没有,我会做更多的挖掘
    • @Barry:类加载器使用正斜杠 / 作为路径分隔符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 2014-01-01
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    相关资源
    最近更新 更多