基于命令行参数的log4j2动态文件名 [英] log4j2 dynamic file name based on command line argument

查看:202
本文介绍了基于命令行参数的log4j2动态文件名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用一个相当简单的log4j2.xml配置文件来登录到stdout.但是,在某些情况下,我们希望在应用程序启动后以编程方式更改此配置,以使用在命令行上移交的日志文件.

为此,我遵循了log4j2主页上的建议,并编写了以下方法

static void divertLogging(String logFile, Level level) {
    ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();

    AppenderComponentBuilder appenderBuilder 
        = builder.newAppender("File", "FILE").addAttribute("fileName", logFile).addAttribute("append", "false");

    appenderBuilder.add(builder.newLayout("PatternLayout")
        .addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));

    builder.add(appenderBuilder);
    builder.add(builder.newRootLogger(level).add(builder.newAppenderRef("File")));

    try {
        builder.writeXmlConfiguration(System.out);
    } catch (IOException e) {
        throw new ApplicationException(e);
    }

    BuiltConfiguration configuration = builder.build();

    Configurator.initialize(configuration);
    ((LoggerContext)LogManager.getContext(false)).updateLoggers(configuration);
}

我们得到以下输出

<?xml version="1.0" ?>
<Configuration>
    <Appenders>
        <FILE name="File" fileName="test.log" append="false">
            <PatternLayout pattern="%d [%t] %-5level: %msg%n%throwable"/>
        </FILE>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="File"/>
        </Root>
    </Loggers>
</Configuration>

,然后是日志消息

ERROR Attempted to append to non-started appender File

此后,日志继续输出到stdout,所需的日志文件保持为空.

有人知道我在做什么错吗?

解决方案

您不需要编程配置即可完成所需的工作,因此我强烈劝阻您不要使用它,因为这会使您的代码依赖于log4j2实现而不是其公共界面.

要在运行时动态更改文件,可以将RoutingAppender log4j2常见问题解答页面.

这是一个示例log4j2配置:

<?xml version="1.0" ?>
<Configuration>
    <Appenders>
        <Routing name="myAppender">
            <Routes pattern="$${main:0}">
                <!-- This route is chosen if there is no value for main argument 0 -->
                <Route key="$${main:0}">
                    <File
                        fileName="logs/default.log"
                        name="myAppender-default">
                        <PatternLayout pattern="%d [%t] %-5level: %msg%n%throwable"/>
                    </File>
                </Route>
                <!-- This route is chosen if there is a value for main argument 0 -->
                <Route>
                    <File
                        fileName="logs/${main:0}.log"
                        name="myAppender-${main:0}">
                        <PatternLayout pattern="%d [%t] %-5level: %msg%n%throwable"/>
                    </File>
                </Route>
            </Routes>
        </Routing>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="myAppender"/>
        </Root>
    </Loggers>
</Configuration>

以下是一些示例Java代码,用于生成一些日志:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.core.lookup.MainMapLookup;

public class SomeClass {

    private static final Logger LOG = LogManager.getLogger();   

    public static void main(String[] args){
        MainMapLookup.setMainArguments(args);

        LOG.info("This should appear in default.log");

        args = new String[]{"specialFile"};
        MainMapLookup.setMainArguments(args);
        LOG.info("This should appear in specialFile.log");
    }
}

在不传递程序参数的情况下执行上述代码时,将生成2个日志,每个日志有1个条目. default.log包含第一个日志条目,而specialFile.log包含第二个日志条目.如果您传递程序参数,它将用作日志文件名,在这种情况下,default.log中将不会出现任何条目-如第二个日志所示,在该日志中,我们通过创建新的String数组来模拟传递单个参数. /p>

希望这会有所帮助!

We are using a fairly simple log4j2.xml configuration file to log to stdout. However there are cases where we want to change this configuration programmatically after the start of the application to use a log file that is handed over on the command line.

For this I followed the suggestion on the log4j2 homepage and wrote the following method

static void divertLogging(String logFile, Level level) {
    ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();

    AppenderComponentBuilder appenderBuilder 
        = builder.newAppender("File", "FILE").addAttribute("fileName", logFile).addAttribute("append", "false");

    appenderBuilder.add(builder.newLayout("PatternLayout")
        .addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));

    builder.add(appenderBuilder);
    builder.add(builder.newRootLogger(level).add(builder.newAppenderRef("File")));

    try {
        builder.writeXmlConfiguration(System.out);
    } catch (IOException e) {
        throw new ApplicationException(e);
    }

    BuiltConfiguration configuration = builder.build();

    Configurator.initialize(configuration);
    ((LoggerContext)LogManager.getContext(false)).updateLoggers(configuration);
}

We get the following output

<?xml version="1.0" ?>
<Configuration>
    <Appenders>
        <FILE name="File" fileName="test.log" append="false">
            <PatternLayout pattern="%d [%t] %-5level: %msg%n%throwable"/>
        </FILE>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="File"/>
        </Root>
    </Loggers>
</Configuration>

and then the log message

ERROR Attempted to append to non-started appender File

After that logging continues to be output to stdout and the desired log file stays empty.

Anyone having an idea what I am doing wrong?

解决方案

You don't need programmatic configuration to do what you want, and I would strongly discourage you from using it since that would make your code depend on the log4j2 implementation rather than its public interface.

To change the file dynamically at runtime you can use the RoutingAppender together with a lookup. See the log4j2 FAQ page for details.

Here is a sample log4j2 configuration:

<?xml version="1.0" ?>
<Configuration>
    <Appenders>
        <Routing name="myAppender">
            <Routes pattern="$${main:0}">
                <!-- This route is chosen if there is no value for main argument 0 -->
                <Route key="$${main:0}">
                    <File
                        fileName="logs/default.log"
                        name="myAppender-default">
                        <PatternLayout pattern="%d [%t] %-5level: %msg%n%throwable"/>
                    </File>
                </Route>
                <!-- This route is chosen if there is a value for main argument 0 -->
                <Route>
                    <File
                        fileName="logs/${main:0}.log"
                        name="myAppender-${main:0}">
                        <PatternLayout pattern="%d [%t] %-5level: %msg%n%throwable"/>
                    </File>
                </Route>
            </Routes>
        </Routing>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="myAppender"/>
        </Root>
    </Loggers>
</Configuration>

Here is some sample Java code to generate some logs:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.core.lookup.MainMapLookup;

public class SomeClass {

    private static final Logger LOG = LogManager.getLogger();   

    public static void main(String[] args){
        MainMapLookup.setMainArguments(args);

        LOG.info("This should appear in default.log");

        args = new String[]{"specialFile"};
        MainMapLookup.setMainArguments(args);
        LOG.info("This should appear in specialFile.log");
    }
}

When the above code is executed without passing a program argument, 2 logs are generated each with 1 entry. The default.log contains the first log entry and the specialFile.log contains the second. If you pass a program argument it will be used as the log file name in which case no entry would appear in default.log - as illustrated by the second log where we simulate passing a single argument by creating the new String array.

Hope this helps!

这篇关于基于命令行参数的log4j2动态文件名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆