как установить loglevel из INFO в ERROR, используя log4j2 api во время выполнения?

17
Метод

logger.setLevel () недоступен в API log4j2. Итак, как установить уровень журнала во время выполнения.

    
задан Nandan 19.06.2013 в 10:16
источник
  • Возможный дубликат программного изменения уровня журнала в Log4j2 –  Martin Schröder 01.02.2017 в 11:33

5 ответов

11

Я не уверен, что это лучший способ, но вы установили уровень в org.apache.logging.log4j.core.config.LoggerConfig , который вы можете получить из LoggerContext через LogManager.

После установки вы можете обновить регистраторы с новой конфигурацией.

Как пример:

public static void main(String[] args) {
    Logger log = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
    log.error("An error");
    log.debug("A debug");

    LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    Configuration conf = ctx.getConfiguration();
    conf.getLoggerConfig(LogManager.ROOT_LOGGER_NAME).setLevel(Level.DEBUG);
    ctx.updateLoggers(conf);

    log.error("Another error");
    log.debug("Another debug");
}

Урожайность:

14:03:41.346 [main] ERROR  - An error
14:03:41.348 [main] ERROR  - Another error
14:03:41.348 [main] DEBUG  - Another debug
    
ответ дан amcintosh 23.08.2013 в 20:04
  • Хорошо работает для корневого регистратора, но не работает, например, для любого другого регистратора - для каждого пакета. В этом случае уровень журнала остается неизменным даже при вызове переконфигурации в контексте. –  amoe 11.12.2013 в 12:27
  • @amoe такой же вопрос здесь. Я предполагаю, что это связано с правильным контекстом в программе webapp. Вы менеджер, чтобы изменить весь уровень регистратора? –  oak 10.08.2014 в 11:25
7

Благодарю amcintosh, я завернул ответ в функцию:

/** Override the logging level of a given logger, return the previous level */
public static Level setLevel(Logger log, Level level) {
  LoggerContext ctx = (LoggerContext)LogManager.getContext(false);
  Configuration conf = ctx.getConfiguration();
  LoggerConfig lconf = conf.getLoggerConfig(log.getName());
  Level oldLevel = lconf.getLevel();
  lconf.setLevel(level);
  ctx.updateLoggers(conf);
  return oldLevel;
}

Несмотря на комментарии amoe, мне кажется, это работает правильно, используя Log4J 2.5.

    
ответ дан dimo414 13.02.2014 в 20:54
  • Может ли он быть настроен для конкретного потока? Поведение такое же, как ThreadContext. –  theGamblerRises 16.08.2016 в 16:44
  • @theGamblerRises Я бы предложил опубликовать отдельный вопрос, а не пытаться изучить это в комментариях. Оффлайн, я бы предположил, что вы не можете контролировать уровни журналов в потоке с помощью этого механизма, но вполне могут быть другие способы делать то, что вы хотите. Если вы разместите отдельный вопрос, не стесняйтесь поделиться ссылкой на него здесь. –  dimo414 17.08.2016 в 16:53
5

Со своей стороны, мне пришлось использовать этот код, чтобы все работало нормально (основываясь на предыдущих ответах).

import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.AbstractConfiguration;

...

public static void changeLoggerLevel(final String module, final Level level) {
  String moduleRenamed = module.replaceAll("/", ".");
  LoggerContext ctx = (LoggerContext)LogManager.getContext(false);
  AbstractConfiguration configuration = (AbstractConfiguration) ctx
        .getConfiguration();
  if (configuration.getLogger(moduleRenamed) != null) {
    LoggerConfig loggerConfig = configuration.getLoggerConfig(moduleRenamed);
    loggerConfig.setLevel(level);
  } else {
    LoggerConfig loggerConfig = new LoggerConfig(moduleRenamed, level, true);
    configuration.addLogger(moduleRenamed, loggerConfig);
  }
  ctx.updateLoggers(configuration);
}

Проблема была в getLoggerConfig() call; если модуль, который вы пытаетесь задать для нового уровня, еще не зарегистрирован, этот метод возвращает корневой логгер (или любой зарегистрированный промежуточный подпуть), и, таким образом, вместо изменения уровня для com.mycompany , вы измените root или com level. Вот почему вы должны добавить новый LoggerConfig , если модуль для изменения еще не зарегистрирован.     

ответ дан SRG 22.09.2014 в 18:39
  • Хороший улов, это поведение документировано, но не то, что обычно ожидали люди. Если я понимаю, что вы говорите, это можно было бы разрешить, просто гарантируя, что Logger существует до вызова getLoggerConfig (), правильно? –  dimo414 22.09.2014 в 19:46
  • Я не пытался, но я бы сказал, что регистратор наследуется от предыдущего (верхнего) уровня (возможно, root), и поэтому всегда определяется ... похоже, это просто наследование конфигурации, которое не полностью (и эта конфигурация должна быть изменена для изменения уровня журнала, а не самого журнала). –  SRG 22.09.2014 в 22:52
  • сделал трюк, спасибо! –  leeor 04.06.2016 в 01:22
  • Отлично работает для Log4j 2.5. Спасибо –  bkrish 03.02.2017 в 17:38
3
ответ дан Gary Gregory 09.01.2016 в 07:20
2

Гэри Грегори прав.

Также ответ на этот вопрос можно найти прямо на странице часто задаваемых вопросов на сайте log4j2

Ссылка

Пример кода ниже:

Configurator.setLevel(logger.getName(), Level.INFO);
    
ответ дан Sudeep Shakya 07.04.2017 в 18:05
  • Хотя это может теоретически ответить на вопрос, было бы предпочтительнее включить основные части ответа здесь и предоставить ссылку для справки. –  Draken 07.04.2017 в 18:36
  • Обновленный ответ с образцом кода. –  Sudeep Shakya 10.04.2017 в 22:58