java - log4j2 基于命令行参数的动态文件名

标签 java log4j2

我们使用一个相当简单的 log4j2.xml 配置文件来记录到标准输出。然而,在某些情况下,我们希望在应用程序启动后以编程方式更改此配置,以使用在命令行上移交的日志文件。

为此我按照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

之后,日志记录继续输出到标准输出,并且所需的日志文件保持为空。

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

最佳答案

您不需要编程配置来执行您想要的操作,我强烈建议您不要使用它,因为这会使您的代码依赖于 log4j2 实现而不是其公共(public)接口(interface)。

要在运行时动态更改文件,您可以使用 RoutingAppenderlookup 一起。请参阅log4j2 FAQ page了解详情。

这是一个示例 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 来模拟传递单个参数。数组。

希望这有帮助!

关于java - log4j2 基于命令行参数的动态文件名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58096611/

相关文章:

java - 无法让Tomcat的java.util日志记录与特定类一起使用

java - 如何使用java停止正在运行的批处理文件

yaml - 在 Log4J2 YAML 中使用属性

java - 从控制台启动 OSGI 时 Log4j2 不工作(在 Eclipse 中工作)

java - log4j2 LogManager.getLogger() 是线程安全的吗?

java - 如何将音频流转换为 .wav 文件并保存

Java——将工作日数转换为天数

java - 如何在 Java 迭代器中获取 JSON 值

java - 来自 log4j2 的奇怪日志

spring-boot - Spring Boot 日志记录 : use of system variables in log4j2. xml