web-dev-qa-db-de.com

Programmgesteuertes Ändern der Protokollebene in Log4j2

Ich bin daran interessiert, die Protokollebene in Log4j2 programmgesteuert zu ändern. Ich habe versucht, ihre Konfigurationsdokumentation anzusehen, aber das schien nichts zu haben. Ich habe auch versucht, im Paket zu suchen: org.Apache.logging.log4j.core.config, aber auch nichts darin sah hilfreich aus.

91
CorayThan

Die von @slaadvak akzeptierte Antwort hat für Log4j2 2.8.2 nicht funktioniert. Folgendes tat es.

Um das Protokoll Level universell zu ändern , verwenden Sie:

Configurator.setAllLevels(LogManager.getRootLogger().getName(), level);

Um das Protokoll Level nur für die aktuelle Klasse zu ändern, verwenden Sie:

Configurator.setLevel(LogManager.getLogger(CallingClass.class).getName(), level);
25
4myle

Wenn Sie eine bestimmte Protokollierungsstufe ändern möchten (nicht die Stammprotokollierungsstufe oder die Stammprotokollierungsstufen, die in der Konfigurationsdatei konfiguriert sind), können Sie dies tun:

public static void setLevel(Logger logger, Level level) {
    final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final Configuration config = ctx.getConfiguration();

    LoggerConfig loggerConfig = config.getLoggerConfig(logger.getName());
    LoggerConfig specificConfig = loggerConfig;

    // We need a specific configuration for this logger,
    // otherwise we would change the level of all other loggers
    // having the original configuration as parent as well

    if (!loggerConfig.getName().equals(logger.getName())) {
        specificConfig = new LoggerConfig(logger.getName(), level, true);
        specificConfig.setParent(loggerConfig);
        config.addLogger(logger.getName(), specificConfig);
    }
    specificConfig.setLevel(level);
    ctx.updateLoggers();
}
18
Jörg Friedrich

Ich habe hier eine gute Antwort gefunden: https://garygregory.wordpress.com/2016/01/11/changing-log-levels-in-log4j2/

Mit org.Apache.logging.log4j.core.config.Configurator können Sie die Ebene für einen bestimmten Logger festlegen.

Logger logger = LogManager.getLogger(Test.class);
Configurator.setLevel(logger.getName(), Level.DEBUG);
10
alfred.schalk

Der programmatische Ansatz ist eher aufdringlich. Vielleicht sollten Sie die JMX-Unterstützung von Log4J2 überprüfen:

  1. Aktivieren Sie den JMX-Port in Ihrem Anwendungsstart:

    -Dcom.Sun.management.jmxremote.port = [port_num]

  2. Verwenden Sie einen der verfügbaren JMX-Clients (die JVM stellt einen in Java_HOME/bin/jconsole.exe bereit), während Sie Ihre Anwendung ausführen.

  3. Suchen Sie in JConsole nach der Bean "org.Apache.logging.log4j2.Loggers"

  4. Ändern Sie abschließend die Stufe Ihres Loggers

Das, was mir am besten gefällt, ist, dass Sie Ihren Code oder Ihre Konfiguration nicht ändern müssen, um dies zu verwalten. Es ist alles äußerlich und transparent.

Weitere Informationen: http://logging.Apache.org/log4j/2.x/manual/jmx.html

4
Victor

Die meisten Antworten gehen standardmäßig davon aus, dass die Protokollierung additiv sein muss. Angenommen, ein Paket generiert viele Protokolle und Sie möchten die Protokollierung nur für diesen bestimmten Protokollierer deaktivieren. Hier ist der Code, mit dem ich es zum Laufen gebracht habe

    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();
    }
}

Ein Testfall für das gleiche

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");
    }
}

Angenommen, die Datei log4j2.xml befindet sich im Klassenpfad

<?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>
2
hobgoblin

Eine ungewöhnliche Möglichkeit, die ich gefunden habe, besteht darin, zwei separate Dateien mit unterschiedlichen Protokollierungsstufen zu erstellen.
Beispielsweise. log4j2.xml und log4j-debug.xml Ändern Sie nun die Konfiguration in diesen Dateien.
Beispielcode:

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));
1
dpp.2325