Программно изменить уровень журнала в Log4j2



Я заинтересован в программном изменении уровня журнала в Log4j2. Я пытался смотреть на их настройки документация но это, казалось, не было ничего. Я также попытался посмотреть в пакете:org.apache.logging.log4j.core.config, но ничего там не выглядело полезным либо.

335   7  

7 ответов:

отредактировано в соответствии с log4j2 версии 2.4 FAQ

вы можете установить уровень регистратора с Конфигуратором класса из ядра Log4j. но имейте в виду, что класс конфигуратора не является частью публичного API.

// org.apache.logging.log4j.core.config.Configurator;
Configurator.setLevel("com.example.Foo", Level.DEBUG);

// You can also set the root logger:
Configurator.setRootLevel(Level.DEBUG);

источник

отредактировано для отражения изменений в API, введенных в Log4j2 версии 2.0.2

Если вы хотите изменить уровень корневого регистратора, сделать что-то подобное :

LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME); 
loggerConfig.setLevel(level);
ctx.updateLoggers();  // This causes all Loggers to refetch information from their LoggerConfig.

здесь является javadoc для LoggerConfig.

Если вы хотите изменить один определенный уровень регистратора (не корневой регистратор или регистраторы, настроенные в файле конфигурации), вы можете сделать это:

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

принятый ответ @slaadvak не работал для меня для Log4j2 2.8.2. Это сделали следующие.

изменить журнал Levelуниверсальное использование:

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

изменить журнал Level только для текущего класса, использовать:

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

Я нашел хороший ответ здесь: https://garygregory.wordpress.com/2016/01/11/changing-log-levels-in-log4j2/

вы можете использовать org.апаш.лесозаготовительный.log4j. core.конфиг.Конфигуратор для установки уровня для конкретного регистратора.

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

программный подход является довольно навязчивым. Возможно, вам следует проверить поддержку JMX, предоставленную Log4J2:

  1. включите порт JMX в вашем приложении start up:

    - Dcom.солнце.управление.jmxremote.port=[port_num]

  2. используйте любой из доступных клиентов JMX (JVM предоставляет один в JAVA_HOME/bin/jconsole.exe) при выполнении вашего приложения.

  3. в JConsole ищите "орг.апаш.лесозаготовительный.log4j2.Лесорубы " Боб

  4. наконец-то изменить уровень вашего регистратора

больше всего мне нравится то, что вам не нужно изменять свой код или конфигурацию для управления этим. Его все внешние и прозрачные.

дополнительная информация:http://logging.apache.org/log4j/2.x/manual/jmx.html

большинство ответов по умолчанию предполагают, что ведение журнала должно быть аддитивным. Но скажите, что какой-то пакет генерирует много журналов, и вы хотите отключить ведение журнала только для этого конкретного регистратора. Вот код, который я использовал, чтобы заставить его работать

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

тестовый случай для того же

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

предполагая следующее log4j2.xml находится в classpath

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

один необычный способ, который я нашел, это создать два отдельных файла с разным уровнем ведения журнала.
например. log4j2.xml и log4j-отладка.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));

Comments

    Ничего не найдено.