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

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

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

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

编辑:对于最新版本的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 { //... } 

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

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

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

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

正如我上面提到的,我无法得到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返回名字。 哪个没有意义……但是自从工作以来,我已经厌倦了在一些应该如此简单的事情上浪费时间……

在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() – >运行良好!!