如何以编程方式在运行时添加Log4J2 appender?

时间:2013-03-15 20:24:44

标签: java logging log4j log4j2

是否可以使用XML配置中的规范以编程方式添加Log4J2 appender?

我计划在log4j2.xml中定义所有内容,然后像这样选择appender(不会编译):

if (arg[0].equals("log") ) {
    Logger.getLogger("loggerNameFromXMLConfig").addAppender("appenderNameFromXMLConfig");
} else {
    //...
}

5 个答案:

答案 0 :(得分:25)

有许多请求支持Log4j 2的更好的编程配置。抱歉,花了这么长时间。从Log4j 2.4开始,API被添加到log4j-core以方便programmatic configuration

新的ConfigurationBuilder API允许用户构建组件定义。使用此API,无需直接使用实际配置对象(如LoggerConfig和FileAppender),这些对象需要大量了解Log4j如何在底层工作。组件定义被添加到ConfigurationBuilder中,一旦收集了所有定义,就构造了所有实际配置对象(如Loggers和Appender)。感觉有点像XML配置语法,除了您正在编写Java代码。

请注意,新的ConfigurationBuilder API允许用户代码创建新配置或完全替换现有配置。如果您的用例不同,并且您希望在Log4j启动后以编程方式修改(而不是替换)现有配置,那么您将需要使用实际的配置对象。在这种情况下,请参阅手册的Programmatically Modifying the Current Configuration after Initialization部分。

答案 1 :(得分:18)

编辑:对于最新版本的log4j2,请参阅https://stackoverflow.com/a/33472893/1899566

我得到的印象是他们不希望你这样做,但这对我有用:

if (arg[0].equals("log") ) {
  org.apache.logging.log4j.Logger logger
    = org.apache.logging.log4j.LogManager.getLogger("loggerNameFromXMLConfig");
  org.apache.logging.log4j.core.Logger coreLogger
    = (org.apache.logging.log4j.core.Logger)logger;
  org.apache.logging.log4j.core.LoggerContext context
    = (org.apache.logging.log4j.core.LoggerContext)coreLogger.getContext();
  org.apache.logging.log4j.core.config.BaseConfiguration configuration
    = (org.apache.logging.log4j.core.config.BaseConfiguration)context.getConfiguration();

  coreLogger.addAppender(configuration.getAppender("appenderNameFromXMLConfig"));
} else {
  //...
}

答案 2 :(得分:2)

我不知道它是否有用: 可以通过调用当前配置的addLoggerAppender方法将Appender添加到Logger。 参考:http://logging.apache.org/log4j/2.x/manual/architecture.html

答案 3 :(得分:2)

正如我上面提到的,我无法让https://logging.apache.org/log4j/2.x/manual/customconfig.html#AddingToCurrent工作,至少不是我预期的方式(我的appender永远不会将消息路由到它)。我最终偶然发现了一个适合我的模式 - 允许我在运行时添加一个appender,并让该appender实际上将日志消息路由到它。

编辑我从这里删除了一堆令人困惑的代码,但没有做任何事......

    LoggerContext lc = (LoggerContext) LogManager.getContext(false);
    FileAppender fa = FileAppender.newBuilder().withName("mylogger").withAppend(false).withFileName(new File(outputDirectory, "ConsoleOutput.txt").toString())
            .withLayout(PatternLayout.newBuilder().withPattern("%-5p %d  [%t] %C{2} (%F:%L) - %m%n").build())
            .setConfiguration(lc.getConfiguration()).build();
    fa.start();
    lc.getConfiguration().addAppender(fa);
    lc.getRootLogger().addAppender(lc.getConfiguration().getAppender(fa.getName()));
    lc.updateLoggers();

对我而言,一个关键点是,调用addAppender并直接传递你的appender并不起作用,但似乎要求你的appender返回名字。哪个没有意义......但是自从工作以来,我已经厌倦了在一些应该如此简单的事情上浪费时间......

答案 4 :(得分:0)

在Log4j2结构中

        ---"Config"---
                Appenders
                        Appender(0)
                            Console
                        Appender(1)
                            File
                    LoggerConfigs
                        -- LoggerConfig(0) 
                        -- LoggerConfig(1)
                        -- LoggerConfig(2)

        ----"LoggerConfig"----
                - AppenderRefs
                    -- AppenderRef(0)
                        -- Name Console
                        -- Level : DEBUG
                - Appenders
                    -- Appender(0)
                        -- Name Console
                        -- Level : DEBUG
                - Level -- ALL

loggerConfig.getAppenders() - >将在“Config”中返回Appenders。对我来说这是一个BUG

loggerConfig.getAppenderRefs() - >工作得很好!!