简体   繁体   English

Log4j2 初始化后配置 FileAppender

[英]Configure FileAppender after Log4j2 Initialization

I'm having trouble configuring a new FileAppender for my log4j2 logger.我在为log4j2记录器配置新的FileAppender遇到问题。 The problem is that I only know the path of the file I should be appending my log after the application starts, so I tried following these instructions here for modifying the original configuration after log4j2 is initialized.问题是我只知道我应该在应用程序启动附加我的日志的文件的路径,所以我尝试按照这里的这些说明log4j2初始化后修改原始配置。

I've read a lot of answers regarding similar issues on stack overflow but most of them are for earlier log4j versions, and won't work as they have now implemented that configuration oriented plugin into log4j itself.我已经阅读了很多关于堆栈溢出类似问题的答案,但其中大部分是针对早期的log4j版本,并且无法工作,因为他们现在已经将面向配置的插件实现到 log4j 本身中。

The app successfuly creates the log file but it won't write any content to it .应用程序成功创建了日志文件,但不会向其中写入任何内容 I've put that test log message on ERROR level on purpose so I could verify it wasn't any issue related to the log level threshold or something.我故意将该测试日志消息放在ERROR级别,以便我可以验证它与日志级别阈值或其他内容无关。

I'm kind of new to log4j2 configuration and feeling a bit lost at this point.我对 log4j2 配置有点陌生,此时感觉有点迷茫。

My log4j2.xml file (very basic) looks like this:我的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>

Also, here's the method that should be adding that new FileAppender :此外,这是应该添加新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");
}

And my Main method, which the very first thing it does is try to change the logger config to write into the file I want:还有我的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");

        ...
 }

What do you mean that you only know the path after the application starts?你的意思是你只知道应用程序启动后的路径? No matter what, you should always be able to use a Lookup to determine the file path.无论如何,您应该始终能够使用查找来确定文件路径。 If the path is specified as one of the arguments to the application you should be able to use the main arguments lookup.如果路径被指定为应用程序的参数之一,您应该能够使用主参数查找。

To be clear, your configuration should something like:需要明确的是,您的配置应该类似于:

<?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>

Note that I have configured a File appender.请注意,我已经配置了一个文件附加程序。 Your sample code is creating a File appender but is naming it "RollingFile" for some reason.您的示例代码正在创建一个文件附加程序,但出于某种原因将其命名为“RollingFile”。

I'm accepting this answer because its related strictly to the question's title.我接受这个答案,因为它与问题的标题严格相关。 If you're checking this post for help you should take a moment to read @rgoers answer as it might be what you're looking for.如果您正在查看这篇文章以寻求帮助,您应该花点时间阅读 @rgoers 的回答,因为它可能正是您要找的。

So here's how I finally did it.所以这就是我最终做到的。 Configuring an existing empty new logger into my log4j2.xml file (as I didn't want to create a new one on runtime) which I would modify on runtime.将现有的空新记录器配置到我的log4j2.xml文件中(因为我不想在运行时创建一个新记录器),我将在运行时修改它。

The issue with my original code was the logger's name.我的原始代码的问题是记录器的名称。 If you take a look at the original post I was creating a new appender named "org.apache.logging.log4j".如果您查看原始帖子,我正在创建一个名为“org.apache.logging.log4j”的新 appender。

On my main class when I retrieved the logger with which I was going to log, I was getting the default's logger for the package in which my main class is ( com.jorge.myapp.business ).在我的主类上,当我检索我要记录的记录器时,我正在获取我的主类所在的包的默认记录器 ( com.jorge.myapp.business )。 Thus, this logger was receiving all the log requests and the new one I created ( org.apache.logging.log4j ) wasn't receiving any.因此,这个记录器接收了所有的日志请求,而我创建的新的( org.apache.logging.log4j )没有接收到任何请求。 That's why it wouldn't log anything to the file I inteded it to, because all logging requests where going to other logger ( com.jorge.myapp.business ).这就是为什么它不会将任何内容记录到我输入的文件中,因为所有记录请求都转到其他记录器( com.jorge.myapp.business )。

I hope this helps somebody, it's a bit confusing to explain... Below more info about my classes and config file:我希望这对某人有所帮助,解释起来有点混乱......下面是关于我的类和配置文件的更多信息:

Modified config file log4j2.xml :修改配置文件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>

This is the initializing method , it retrieves the current log4j2 config from the xml file and modifies the existing logger adding a new file appender这是初始化方法,它从 xml 文件中检索当前的log4j2配置并修改现有的记录器,添加一个新的文件附加程序。

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();
}

Some constants I used ( Constants.java class):我使用的一些常量Constants.java类):

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

More info about how Log4j2 actually works 'under the hood' can be found here , as pointed out by @rgoers.正如@rgoers 指出的那样,可以在此处找到有关 Log4j2 如何在“幕后”实际工作的更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM