Динамічно зміна рівня журналу log4j


127

Назвіть різні підходи до того, щоб динамічно змінювати рівень журналу log4j, щоб мені не довелося перерозподіляти додаток. Чи будуть зміни в цих випадках постійними?




3
Оновлений питання log4j2: stackoverflow.com/questions/23434252 / ...
slaadvak

1
Зверніть увагу, що (майже) все на цій сторінці стосується log4j, а не log4j2. Вся ця сторінка настільки сповнена плутанини та неправильності, що це ПОЛЕ. Перейти до stackoverflow.com/questions/23434252 / ... , як @slaadvak рекомендує.
Ламбарт

Відповіді:


86

Зміна рівня журналу проста; модифікація інших частин конфігурації буде представляти більш глибокий підхід.

LogManager.getRootLogger().setLevel(Level.DEBUG);

Зміни постійні через життєвий цикл Logger. Після повторної ініціалізації конфігурація буде прочитана та використана, оскільки встановлення рівня під час виконання не зберігає змін рівня.

UPDATE: Якщо ви використовуєте Log4j-ви повинні видалити виклики в setLevelвідповідно до документацією , так як це може бути досягнуто з допомогою класів реалізації.

Виклики до logger.setLevel () або подібні методи не підтримуються в API. Програми повинні видалити їх. Еквівалентна функціональність надається у класах реалізації Log4j 2, але може залишати програму сприйнятливою до змін у внутрішніх протоколах Log4j 2.


5
Тільки залежність від часу виконанняLogManager.getLogger(Class.forName("org.hibernate.util.JDBCExceptionReporter")).setLevel(Level.FATAL);
CelinHC

8
Зауважте, що API log4j 2 не забезпечує метод "setLevel".
ChrisCantrell

5
Але це встановлює лише кореневий реєстратор, чи не так? Якщо окремі рівні встановлені для реєстраторів, що знаходяться під коренем, встановлення кореневого реєстратора не матиме впливу на ці LOGGER. Чи не доведеться нам робити щось на зразок root.getLoggerRepository (). GetCurrentCategories (), повторювати кожен екземпляр реєстратора та встановлювати рівні для кожного реєстратора? @AaronMcIver
TheMonkWhoSoldHisCode

8
@ChrisCantrell Log4j 2 дає спосіб зробити це , хоча це не так просто.
CorayThan

2
Log4j2 можна налаштувати на оновлення конфігурації, сканувавши файл log4j2.xml (або еквівалент) через задані інтервали. Наприклад, <Configuration status = "warn" monitorInterval = "5" name = "tryItApp" пакети = "">
Kimball Robinson

89

Файл сторожовий

Log4j може переглядати log4j.xmlфайл за зміною конфігурації. Якщо ви зміните файл log4j, log4j автоматично оновить рівні журналу відповідно до ваших змін. Докладніше див. У документації org.apache.log4j.xml.DOMConfigurator.configureAndWatch(String,long). Час очікування за замовчуванням між чеками - 60 секунд. Ці зміни будуть постійними, оскільки ви безпосередньо змінюєте файл конфігурації у файловій системі. Все, що вам потрібно зробити - це один раз викликати DOMConfigurator.configureAndWatch () один раз.

Увага: метод configureAndWatch небезпечний для використання в середовищах J2EE через витік нитки

JMX

Інший спосіб встановити рівень журналу (або перенастроювати загалом) log4j - це використовувати JMX. Log4j реєструє свої реєстратори як JMX MBeans. Використовуючи консолі MBeanServer серверів прикладних програм (або jconsole.exe JDK), ви можете налаштувати кожен окремий реєстратор. Ці зміни не є стійкими, і вони будуть скинуті до конфігурації, встановленої у файлі конфігурації після перезавантаження програми (сервера).

Саморобний

Як описано Аароном, ви можете встановити рівень журналу програмно. Ви можете реалізувати його у своїй програмі так, як ви хотіли б, щоб це сталося. Наприклад, у вас може бути графічний інтерфейс користувача, коли користувач або адміністратор змінює рівень журналу, а потім викликає setLevel()методи в реєстраторі. Незалежно від того, чи будете ви зберігати налаштування десь чи ні.


8
Обережне слово щодо підходу сторожового журналу log4j: "Оскільки configureAndWatch запускає окремий потік сторожової собаки і тому, що немає можливості зупинити цей потік у log4j 1.2, метод configureAndWatch небезпечний для використання в середовищі J2EE, де додатки переробляються". Довідка: FAQ FAQ4
Somu

Якби я мав використовувати функцію configureAndWatch Log4j, я міг би зупинити цю сторожову нитку методом @PostDestroy EJB (це досить хороший показник, коли контейнер закривається) Це все? Або є більше цього, чого я сумую ..!
robin bajaj

Вибачте, що я мав на увазі метод @PreDestroy
Робін bajaj

" Log4j реєструє свої реєстратори як JMX MBeans. " Мій сервлет використовує log4j 1.2 Я не бачу log4j MBeans.
Абдул

Все, що вам потрібно зробити - це один раз викликати DOMConfigurator.configureAndWatch () один раз. Як я можу цього досягти?
gstackoverflow

5

Log4j2 можна налаштувати на оновлення конфігурації, скануючи файл log4j 2 .xml (або еквівалент) через задані інтервали. Просто додайте параметр " monitorInterval " у свій тег налаштування. Дивіться рядок 2 зразка файла log4j 2 .xml, який повідомляє log4j повторно сканувати його конфігурацію, якщо з останньої події журналу минуло більше 5 секунд.

<?xml version="1.0" encoding="UTF-8" ?>
<Configuration status="warn" monitorInterval="5" name="tryItApp" packages="">

    <Appenders>
        <RollingFile name="MY_TRY_IT"
                     fileName="/var/log/tryIt.log"
                     filePattern="/var/log/tryIt-%i.log.gz">
            <Policies>
                <SizeBasedTriggeringPolicy size="25 MB"/>
            </Policies>
            ...
        </RollingFile>
    </Appenders>


    <Loggers>
        <Root level="error">
            <AppenderRef ref="MY_TRY_IT"/>
        </Root>
    </Loggers>

</Configuration>

Існують додаткові кроки, щоб зробити цю роботу, якщо ви розгортаєтесь до екземпляра tomcat, всередині IDE або під час використання весняного завантаження. Це виглядає дещо поза рамками і, ймовірно, заслуговує окремого питання.


@vsingh, ви розміщуєте всередині весняного завантаження, tomcat чи контейнера чи з IDE? Іноді в цих випадках можуть бути додаткові кроки (не з вини log4j2) - в основному додаток не бачить зміни файлу, оскільки він скопійований у інше місце рамкою чи інструментом.
Кімбол Робінсон

Привіт, я перевірив це на Jboss6.4, і я оновив конфігураційний файл log4j2 під розташуванням (всередині .war файлу), де додаток може бачити файл. Однак все одно не вийшло. Будь-яка пропозиція?
MidTierDeveloper

3

Ця відповідь не допоможе вам змінити рівень журналу динамічно. Вам потрібно перезапустити послугу, якщо ви добре перезапустили службу, будь ласка, скористайтеся наведеним нижче рішенням

Я зробив це, щоб змінити рівень журналу log4j, і він працював на мене, я не пересилав жодного документа. Я використовував це системне значення властивості, щоб встановити своє ім'я файлу журналу. Я використовував ту саму техніку, щоб встановити рівень журналу, і він працював

передав це як параметр JVM (я використовую Java 1.7)

На жаль, це не змінить динамічно рівень журналу, він вимагає перезавантаження служби

java -Dlogging.level=DEBUG -cp xxxxxx.jar  xxxxx.java

у файл log4j.properties я додав цей запис

log4j.rootLogger=${logging.level},file,stdout

я намагався

 java -Dlogging.level=DEBUG -cp xxxxxx.jar  xxxxx.java
 java -Dlogging.level=INFO-cp xxxxxx.jar  xxxxx.java
 java -Dlogging.level=OFF -cp xxxxxx.jar  xxxxx.java

Це все спрацювало. сподіваюся, що це допомагає!

У моїх файлах pom.xml у мене такі залежності

<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
</dependency>

<dependency>
    <groupId>log4j</groupId>
    <artifactId>apache-log4j-extras</artifactId>
    <version>1.2.17</version>
</dependency>

2
Все, що ви згадали, здається нормальним, але питання про динамічну зміну рівня журналу.
Азим

Для цього вам потрібно перезапустити послугу. Це не змінює рівні реєстрації динамічно.
кк.

2

З log4j 1.x я вважаю, що найкращим способом є використання DOMConfigurator для подання одного заздалегідь заданого набору конфігурацій журналу XML (скажімо, для нормального використання та одного для налагодження).

Використовуючи їх, можна виконати щось подібне:

  public static void reconfigurePredefined(String newLoggerConfigName) {
    String name = newLoggerConfigName.toLowerCase();
    if ("default".equals(name)) {
      name = "log4j.xml";
    } else {
      name = "log4j-" + name + ".xml";
    }

    if (Log4jReconfigurator.class.getResource("/" + name) != null) {
      String logConfigPath = Log4jReconfigurator.class.getResource("/" + name).getPath();
      logger.warn("Using log4j configuration: " + logConfigPath);
      try (InputStream defaultIs = Log4jReconfigurator.class.getResourceAsStream("/" + name)) {
        new DOMConfigurator().doConfigure(defaultIs, LogManager.getLoggerRepository());
      } catch (IOException e) {
        logger.error("Failed to reconfigure log4j configuration, could not find file " + logConfigPath + " on the classpath", e);
      } catch (FactoryConfigurationError e) {
        logger.error("Failed to reconfigure log4j configuration, could not load file " + logConfigPath, e);
      }
    } else {
      logger.error("Could not find log4j configuration file " + name + ".xml on classpath");
    }
  }

Просто зателефонуйте до цього за допомогою відповідного імені конфігурації та переконайтеся, що ви розмістили шаблони на класі.


що є запускаючою точкою цього методу? як відомо, що цей метод потрібно викликати, коли в конфігурації log4j є зміна?
асгс

Я досі не розумію, що ви маєте на увазі "на вимогу". Чи можете ви, будь ласка, показати фрагмент, де підключити цей метод?
асгс

2
Ось вам: Це фрагмент від Контролера, де ми його використовуємо. У нас є адміністративна сторінка з деякими посиланнями для динамічного перенастроювання журналу, яка потім робить GET на link / admin / setLogLevel? Level = Помилка і потім ми вловлюємо
ISparkes

Отже, "на запит" означає "коли користувач натискає кнопку" в моєму випадку
ISparkes

Ах, ти взяв. Отже, ваша консоль адміністратора повинна подати запит на використання цього методу.
асгс

0

Я успішно використовував цей метод, щоб зменшити багатослівність журналів "org.apache.http":

ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("org.apache.http");
logger.setLevel(Level.TRACE);
logger.setAdditive(false);

0

Для API log4j 2 ви можете використовувати

Logger logger = LogManager.getRootLogger();
Configurator.setAllLevels(logger.getName(), Level.getLevel(level));

-1

Якщо ви хочете змінити рівень реєстрації всіх реєстраторів, скористайтеся методом нижче. Це перерахує всі реєстратори та змінить рівень журналу на заданий рівень. Переконайтеся, що у вашому файлі НЕ встановлено log4j.appender.loggerName.Threshold=DEBUGвластивості log4j.properties.

public static void changeLogLevel(Level level) {
    Enumeration<?> loggers = LogManager.getCurrentLoggers();
    while(loggers.hasMoreElements()) {
        Logger logger = (Logger) loggers.nextElement();
        logger.setLevel(level);
    }
}

-3

Ви можете використовувати наступний фрагмент коду

((ch.qos.logback.classic.Logger)LoggerFactory.getLogger(packageName)).setLevel(ch.qos.logback.classic.Level.toLevel(logLevel));

я повинен спробувати це.
користувач2045474
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.