为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

胡说叔叔 2023-08-16 17:23:01
我们使用一个相当简单的 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之后,日志记录继续输出到标准输出,并且所需的日志文件保持为空。有人知道我做错了什么吗?
查看完整描述

2 回答

?
皈依舞

TA贡献1851条经验 获得超3个赞

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

要在运行时动态更改文件,您可以将与LookupRoutingAppender一起使用。

这是 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。


希望这可以帮助!


查看完整回答
反对 回复 2023-08-16
?
jeck猫

TA贡献1909条经验 获得超7个赞

尝试这个


    /**

     * 

     * @param logType 0 = console, 1 = file

     * @param logFile

     * @param level

     */

    private void divertLogging(int logType, String logFile, Level level) {

        ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();


        AppenderComponentBuilder appenderBuilder;


        if (logType == 0)

            appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);

        else

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

        if (logType == 1)

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


        try {

            builder.writeXmlConfiguration(System.out);

        } catch (IOException e) {

            e.printStackTrace();

        }


        BuiltConfiguration configuration = builder.build();


        Configurator.initialize(configuration);

        ((LoggerContext)LogManager.getContext(false)).updateLoggers(configuration);

        if (logType == 1)

            configuration.getAppender("File").start();

    }


    public static void main(String[] args) {

        Log4j2Test test = new Log4j2Test();

        test.divertLogging(0, null, Level.ALL);

        logger.error("Log to console 1");

        test.divertLogging(1, "C:\\Java\\test\\output\\test.log", Level.ALL);

        logger.error("Log to file 2");

        test.divertLogging(0, null, Level.ALL);

        logger.error("Log to console 3");

        test.divertLogging(1, "C:\\Java\\test\\output\\test.log", Level.ALL);

        logger.error("Log to file 4");

    }

为什么我的答案被否决了?


查看完整回答
反对 回复 2023-08-16
  • 2 回答
  • 0 关注
  • 119 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信