如何以编程方式在运行时添加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() – >运行良好!!