【问题标题】:Configure FileAppender after Log4j2 InitializationLog4j2 初始化后配置 FileAppender
【发布时间】:2016-08-21 20:14:21
【问题描述】:

我在为我的 log4j2 记录器配置新的 FileAppender 时遇到问题。问题是我只知道我应该在应用程序启动之后添加日志的文件的路径,所以我尝试按照这些说明here 在初始化log4j2 后修改原始配置.

我已经阅读了很多关于堆栈溢出的类似问题的答案,但其中大多数是针对早期的log4j 版本的,并且由于他们现在已经在 log4j 本身中实现了面向配置的插件,因此无法正常工作。

应用成功创建日志文件,但不会向其中写入任何内容。我故意将该测试日志消息放在ERROR 级别,以便我可以验证它不是与日志级别阈值或其他相关的任何问题。

我是 log4j2 配置的新手,在这一点上感觉有点迷茫。

我的log4j2.xml 文件(非常基本)如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
    <Properties>
        <Property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %logger{36} - %msg%n</Property>
    </Properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
             <PatternLayout pattern="${PATTERN}"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="debug">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

另外,这是应该添加新的FileAppender 的方法:

public static void initLogFile(String path, Level level) {
    final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final Configuration config = ctx.getConfiguration();
    Layout layout = PatternLayout.createDefaultLayout(config);
    Appender appender = FileAppender.createAppender(path, "false", "true",
            "RollingFile", "true", "false", "false", "8000", null, null,
            "false", null, config);
    appender.start();
    config.addAppender(appender);
    AppenderRef ref = AppenderRef.createAppenderRef("RollingFile", null,
            null);
    AppenderRef[] refs = new AppenderRef[] { ref };
    LoggerConfig loggerConfig = LoggerConfig.createLogger("false", level,
            "org.apache.logging.log4j", "true", refs, null, config, null);
    loggerConfig.addAppender(appender, null, null);
    config.addLogger("org.apache.logging.log4j", loggerConfig);
    ctx.updateLoggers();
    System.out.println("Logger initialized");
}

还有我的Main 方法,它所做的第一件事就是尝试更改记录器配置以写入我想要的文件:

static final Logger log = LogManager.getLogger(Main.class.getName());
  public static void main( String[] args )
    {
        // Init
        System.out.println("Initializing logger");
        Utils.initLogFile("C:/Users/Jorge/Desktop/logtest/test.log", Level.DEBUG);

        log.error("test error message");

        ...
 }

【问题讨论】:

    标签: java logging log4j2


    【解决方案1】:

    什么意思是应用启动后才知道路径?无论如何,您应该始终能够使用查找来确定文件路径。如果路径被指定为应用程序的参数之一,您应该能够使用主参数查找。

    为了清楚起见,您的配置应该是这样的:

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="INFO">
    <Properties>
        <Property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %logger{36} - %msg%n</Property>
    </Properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
             <PatternLayout pattern="${PATTERN}"/>
        </Console>
        <File name="file" fileName="${main:--logFile}">
             <PatternLayout pattern="${PATTERN}"/>
        </File> 
    </Appenders>
    <Loggers>
        <Logger name="org.apache.logging.log4j" level="${main:--level}">
           <AppenderRef ref="file"/>
        </Logger>
        <Root level="debug">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
    

    请注意,我已经配置了一个文件附加程序。您的示例代码正在创建一个文件附加程序,但出于某种原因将其命名为“RollingFile”。

    【讨论】:

    • 应用程序的参数之一是日志文件路径。当任何用户通过命令行运行应用程序时,将包含应用程序生成的所有日志的文件的路径(它实际上是一个可运行的 JAR)作为参数传递。我在查找文件时没有遇到问题,我无法写入经过动态配置的 FileAppender
    • 不要动态配置文件追加器。将其添加到配置文件中。只需使用 ${main:--file} 或文件的任何选项来获取文件路径。如果由于某种原因这对您不起作用,您可以创建自己的查找。但是我没有充分的理由可以根据您的描述以编程方式配置附加程序。
    • 也许我的做法不是最好的,你是对的,我应该使用你建议的配置,但我很想知道为什么我的 appender 所在的日志文件created 应该在应用程序执行结束时写入是空的......我对新文件追加器的创建有什么误解?它没有记录任何东西,我不知道为什么。不过,我会按照您的建议尝试解决,但我想了解为什么我的方法不起作用
    • 可能是因为您正在创建的 LoggerConfig 名为 org.apache.logging.log4j。您实际上是否在该包下创建任何记录器?这是非常值得怀疑的。
    • 确实如此!问题在于org.apache.logging.log4j。将其更改为向记录器发送请求的我的应用程序包之一成功并写入文件。我仍然不明白记录器的名称与包有什么关系,但如果你可以在另一个答案中解释我会接受它,因为这是我要求的解决方案。
    【解决方案2】:

    我接受这个答案是因为它与问题的标题严格相关。如果您正在查看这篇文章以寻求帮助,您应该花点时间阅读@rgoers 的答案,因为它可能是您正在寻找的。​​p>

    这就是我最终做到的方式。将现有的空记录器配置到我的 log4j2.xml 文件中(因为我不想在运行时创建一个新记录器),我将在运行时对其进行修改。

    我的原始代码的问题是记录器的名称。如果您查看原始帖子,我正在创建一个名为“org.apache.logging.log4j”的新附加程序。

    在我的主类中,当我检索要记录的记录器时,我得到了我的主类所在包的默认记录器 (com.jorge.myapp.business)。因此,该记录器正在接收所有日志请求,而我创建的新请求 (org.apache.logging.log4j) 没有收到任何请求。这就是为什么它不会将任何内容记录到我集成到的文件中,因为所有记录请求都会转到其他记录器 (com.jorge.myapp.business)。

    我希望这对某人有所帮助,解释起来有点令人困惑......下面是关于我的类和配置文件的更多信息:

    修改config文件log4j2.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="INFO">
        <Properties>
            <Property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %logger{36} - %msg%n</Property>
        </Properties>
        <Appenders>
            <Console name="Console" target="SYSTEM_OUT">
                 <PatternLayout pattern="${PATTERN}"/>
            </Console>
        </Appenders>
        <Loggers>
            <Root level="debug">
                <AppenderRef ref="Console" />
            </Root>
            <Logger name="com.jorge.myapp.business" level="debug">
            </Logger>
    
        </Loggers>
    </Configuration>
    

    这是初始化方法,它从xml文件中检索当前的log4j2配置并修改现有的logger添加一个新的文件appender

    public static void initLogFile(String path, Level level){
    
        final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        final Configuration config = ctx.getConfiguration();
    
        Layout layout = PatternLayout.createLayout(Constants.LOG_PATTERN, null, config, null, null, false, false, null, null);
        Appender appender = FileAppender.createAppender(path, "true", "true", "File", "true",
            "false", "false", null, layout, null, "false", null, config);
        appender.start();
        config.addAppender(appender);
        AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
        AppenderRef[] refs = new AppenderRef[] {ref};
        LoggerConfig loggerConfig = config.getLoggerConfig("com.jorge.myapp.business");
        loggerConfig.addAppender(appender, null, null);
        ctx.updateLoggers();
    }
    

    我使用的一些常量Constants.java 类):

    public static final String LOG_PATTERN = "%d{yyyy-MM-dd HH:mm:ss} [%-5level] MyApp - %msg%n";
    

    如@rgoers 所指出的,有关 Log4j2 如何“在后台”实际工作的更多信息可以在 here 找到。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-04
      • 2011-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多