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

Bri*_*son 33 java logging log4j log4j2

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

我打算在log4j2.xml中定义它,然后像这样选择appender(不会编译):

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

Rem*_*pma 27

已经有很多请求支持Log4j 2的更好的编程配置.抱歉,花了这么长时间.从Log4j 2.4开始,API被添加到log4j-core以便于编程配置.

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

请注意,新ConfigurationBuilderAPI允许用户代码创建新配置或完全替换现有配置.如果您的用例不同,并且您希望在Log4j启动后以编程方式修改(而不是替换)现有配置,那么您将需要使用实际的配置对象.在这种情况下,请参阅本手册中" 以编程方式修改初始化后的当前配置"部分.

  • 我正在考虑放弃 log4j。他们把事情复杂化到了荒谬的地步。你需要 2 小时来编写自己的日志框架,但需要 2 周的时间来研究这些废话。 (5认同)
  • 我会注意到,我一直在寻找这个答案,它指向了文档,但是文档中的示例现在使用了不赞成使用的方法,并且对我实际上没有用。我必须添加这样的内容才能使其正常工作:context.getRootLogger()。addAppender(configuration.getAppender(appender.getName())); 您也无法直接传递附加程序,因为那也不起作用。 (3认同)
  • @RemkoPopma现在是log4j 2.12版本。绝对需要更清洁的API来停止和清除以编程方式创建的附加程序和记录器。 (2认同)

Rob*_*ing 20

编辑:对于最新版本的log4j2,请参阅/sf/answers/2343102541/.

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

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 {
  //...
}
Run Code Online (Sandbox Code Playgroud)

  • 那个好漂亮!:) (2认同)

use*_*960 11

正如我上面提到的,我无法让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();
Run Code Online (Sandbox Code Playgroud)

对我来说一个关键点是,调用 addAppender 并直接传递您的 appender 是行不通的,但似乎可以按名称要求您的 appender。这没有意义......但是自从工作以来,我厌倦了在应该如此简单的事情上浪费时间......

  • 非常感谢您的回答!现在官方文档甚至与log4j 2.14的接口都不匹配。官方文档里应该有这个! (2认同)