La plupart des réponses supposent par défaut que la journalisation doit être additive. Mais disons qu'un paquet génère beaucoup de journaux et que vous souhaitez désactiver la journalisation pour cet enregistreur particulier uniquement. Voici le code que j'ai utilisé pour le faire fonctionner
public class LogConfigManager {
public void setLogLevel(String loggerName, String level) {
Level newLevel = Level.valueOf(level);
LoggerContext logContext = (LoggerContext) LogManager.getContext(false);
Configuration configuration = logContext.getConfiguration();
LoggerConfig loggerConfig = configuration.getLoggerConfig(loggerName);
// getLoggerConfig("a.b.c") could return logger for "a.b" if there is no logger for "a.b.c"
if (loggerConfig.getName().equalsIgnoreCase(loggerName)) {
loggerConfig.setLevel(newLevel);
log.info("Changed logger level for {} to {} ", loggerName, newLevel);
} else {
// create a new config.
loggerConfig = new LoggerConfig(loggerName, newLevel, false);
log.info("Adding config for: {} with level: {}", loggerConfig, newLevel);
configuration.addLogger(loggerName, loggerConfig);
LoggerConfig parentConfig = loggerConfig.getParent();
do {
for (Map.Entry<String, Appender> entry : parentConfig.getAppenders().entrySet()) {
loggerConfig.addAppender(entry.getValue(), null, null);
}
parentConfig = parentConfig.getParent();
} while (null != parentConfig && parentConfig.isAdditive());
}
logContext.updateLoggers();
}
}
Un cas de test pour le même
public class LogConfigManagerTest {
@Test
public void testLogChange() throws IOException {
LogConfigManager logConfigManager = new LogConfigManager();
File file = new File("logs/server.log");
Files.write(file.toPath(), new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
Logger logger = LoggerFactory.getLogger("a.b.c");
logger.debug("Marvel-1");
logConfigManager.setLogLevel("a.b.c", "debug");
logger.debug("DC-1");
// Parent logger level should remain same
LoggerFactory.getLogger("a.b").debug("Marvel-2");
logConfigManager.setLogLevel("a.b.c", "info");
logger.debug("Marvel-3");
// Flush everything
LogManager.shutdown();
String content = Files.readAllLines(file.toPath()).stream().reduce((s1, s2) -> s1 + "\t" + s2).orElse(null);
Assert.assertEquals(content, "DC-1");
}
}
En supposant que log4j2.xml suivant est dans le chemin de classe
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config">
<Appenders>
<File name="FILE" fileName="logs/server.log" append="true">
<PatternLayout pattern="%m%n"/>
</File>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%m%n"/>
</Console>
</Appenders>
<Loggers>
<AsyncLogger name="a.b" level="info">
<AppenderRef ref="STDOUT"/>
<AppenderRef ref="FILE"/>
</AsyncLogger>
<AsyncRoot level="info">
<AppenderRef ref="STDOUT"/>
</AsyncRoot>
</Loggers>
</Configuration>