[英]Log4j2 does not change logging level at runtime
Yes, I've read all the related questions.是的,我已阅读所有相关问题。 I am using log4j2 (tried both version 2.4 and updating to latest, version 2.6.2).我正在使用 log4j2(尝试了 2.4 版并更新到最新的 2.6.2 版)。
I have a small utility program for customers.我有一个供客户使用的小型实用程序。 I'm keen to keep exposed configurations at minimum.我热衷于将暴露的配置保持在最低限度。 But for problematic cases, I'd also want to add a -debug
flag to enable debug logs at runtime.但是对于有问题的情况,我还想添加一个-debug
标志以在运行时启用调试日志。
Here is my code to enable debug logging这是我启用调试日志记录的代码
private static void enableDebugLogs(){
LoggerContext ctx = (LoggerContext) LogManager.getContext();
LoggerConfig log = ctx.getConfiguration().getRootLogger();
System.out.println(log.getLevel()); // INFO
log.setLevel(Level.DEBUG);
System.out.println(log.getLevel()); // DEBUG
ctx.updateLoggers();
System.out.println(ctx.getRootLogger().getLevel()); // DEBUG, hey it works, right?
}
But it does not actually work with any of these cases:但它实际上不适用于以下任何一种情况:
enableDebugLogs();
logger.debug("Debug mode on"); // static, already made logger. Level did not change
LogManager.getLogger(Main.class).debug("Debug"); // Nope, not printing
Logger root = LogManager.getRootLogger();
root.info("Level: " + root.getLevel()); // Level: INFO, should be DEBUG
The utility program is finished usually in less than 30 seconds, so the change should be instant.实用程序通常在 30 秒内完成,因此更改应该是即时的。 Here is the log4j2.xml这是 log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level - %msg%n"/>
</Console>
<RollingFile name="File" fileName="program_name.log" filePattern="program_name-archived.log">
<PatternLayout>
<Pattern>%d{HH:mm:ss.SSS} %-5level - %msg%n</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="10 KB" />
</Policies>
<DefaultRolloverStrategy min="1" max="1"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
Is the problem with usings AppenderRefs?使用 AppenderRefs 有问题吗? Can I somehow tell the Appenders to update logging level from Root logger?我可以以某种方式告诉 Appenders 从根记录器更新日志记录级别吗?
Found the real issue.发现了真正的问题。 Had to use:不得不使用:
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
instead of而不是
LoggerContext ctx = (LoggerContext) LogManager.getContext();
API stating the difference being "returns the LoggerContext" and "returns the current LoggerContext". API 说明区别在于“返回 LoggerContext”和“返回当前 LoggerContext”。 And I clearly missed this bit of information for the version without boolean parameter:我显然错过了没有布尔参数的版本的这一点信息:
"WARNING - The LoggerContext returned by this method may not be the LoggerContext used to create a Logger for the calling class." “警告 - 此方法返回的 LoggerContext 可能不是用于为调用类创建 Logger 的 LoggerContext。”
You can change switch the logging configuration between two or multiple log4j2.xml files.您可以更改两个或多个 log4j2.xml 文件之间的日志记录配置。
For example, create two log4j2.xml files with different configurations.例如,创建两个不同配置的 log4j2.xml 文件。 log4j2.xml & log4j2-debug.xml and pass it to below code. log4j2.xml & log4j2-debug.xml 并将其传递给以下代码。
ConfigurationFactory configFactory = XmlConfigurationFactory.getInstance();
ConfigurationFactory.setConfigurationFactory(configFactory);
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream inputStream = classloader.getResourceAsStream(logFileName);
ConfigurationSource configurationSource = new ConfigurationSource(inputStream);
ctx.start(configFactory.getConfiguration(ctx, configurationSource));
To reconfigure log4j2 after it's initialization, the documentation give you two ways :要在初始化后重新配置 log4j2,文档为您提供了两种方法:
In addition to the above, to debug log4j initialization, set <Configuration status="trace"
in the beginning of the configuration file.除了上面的,要调试log4j初始化,在配置文件的开头设置<Configuration status="trace"
。 Log4j2's internal status logs will print to the console. Log4j2 的内部状态日志将打印到控制台。 This may help troubleshooting.这可能有助于故障排除。
Here is a little known fact.这是一个鲜为人知的事实。 If you set your ROOT_LOGGER level in your log4j2.xml or equivalent properties to say DEBUG, then setting the level dynamically to something lower did not work for me;如果您在 log4j2.xml 或等效属性中将 ROOT_LOGGER 级别设置为 DEBUG,那么将级别动态设置为较低的级别对我来说不起作用; in other words, setting dynamically had no effect.换句话说,动态设置没有效果。 ONLY when I change the setting in log4j2.xml to TRACE and then using the below to change the log level did it work for me:只有当我将 log4j2.xml 中的设置更改为 TRACE然后使用以下内容更改日志级别时才对我有用:
Level level = Level.valueOf(this.consoleLogLevel.toUpperCase());
//Dynamically set the log level for ALL loggers
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
loggerConfig.setLevel(level);
ctx.updateLoggers();
And here is my simple configuration file:这是我的简单配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="TRACE">
<AppenderRef level="TRACE" ref="Console" />
</Root>
</Loggers>
</Configuration>
And here is a TestNG test you can refactor to verify the above:这是一个 TestNG 测试,您可以重构以验证上述内容:
@Test
public void givenCut_whenLoggingWithERRORLevel_LoggingOutputIsAtERRORLevelAndHigherOnly() {
try {
lcaProperties.setLogLevel(Level.ERROR.name());
GlobalLogger globalLogger = GlobalLogger.builder().lcaServiceProperties(lcaProperties).build();
assertNotNull(globalLogger.getConsoleLogger());
assertNotNull(globalLogger.getFunctionalDbLogger());
assertEquals(globalLogger.getConsoleLogger().getLevel(), Level.ERROR);
assertEquals(log.getLevel(), Level.ERROR);
System.out.println("log.getLogLevel() = " + log.getLevel());
System.out.println("globalLogger.getConsoleLogger().getLevel() = " + globalLogger.getConsoleLogger().getLevel());
log.fatal("logLevel::"+log.getLevel()+"::log.fatal");
log.error("logLevel::"+log.getLevel()+"::log.error");
log.warn("logLevel::"+log.getLevel()+"::log.warn");
log.info("logLevel::"+log.getLevel()+"::log.info");
log.debug("logLevel::"+log.getLevel()+"::log.debug");
log.trace("logLevel::"+log.getLevel()+"::log.trace");
globalLogger.getConsoleLogger().fatal("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"::globalLogger.getConsoleLogger().fatal");
globalLogger.getConsoleLogger().error("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"::globalLogger.getConsoleLogger().debug");
globalLogger.getConsoleLogger().warn("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"::globalLogger.getConsoleLogger().debug");
globalLogger.getConsoleLogger().info("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"::globalLogger.getConsoleLogger().debug");
globalLogger.getConsoleLogger().debug("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"::globalLogger.getConsoleLogger().debug");
globalLogger.getConsoleLogger().trace("logLevel::"+globalLogger.getConsoleLogger().getLevel()+"globalLogger.getConsoleLogger()::log.trace");
} catch (Exception e) {
fail();
log.error(e);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.