Почему такой уровень.Штраф регистрации сообщений не отображается?



The JavaDocs для java.util.logging.Level состояние:





уровни в порядке убывания являются:





  • SEVERE (максимальное значение)

  • WARNING

  • INFO

  • CONFIG

  • FINE

  • FINER


  • FINEST (самое низкое значение)




источник



import java.util.logging.*;

class LoggingLevelsBlunder {

public static void main(String[] args) {
Logger logger = Logger.getAnonymousLogger();
logger.setLevel(Level.FINER);
System.out.println("Logging level is: " + logger.getLevel());
for (int ii=0; ii<3; ii++) {
logger.log(Level.FINE, ii + " " + (ii*ii));
logger.log(Level.INFO, ii + " " + (ii*ii));
}
}
}


выход



Logging level is: FINER
Jun 11, 2011 9:39:23 PM LoggingLevelsBlunder main
INFO: 0 0
Jun 11, 2011 9:39:24 PM LoggingLevelsBlunder main
INFO: 1 1
Jun 11, 2011 9:39:24 PM LoggingLevelsBlunder main
INFO: 2 4
Press any key to continue . . .


проблема заявление



мой пример устанавливает Level до FINER, так что я ожидал увидеть 2 сообщения для каждого цикла. Вместо этого я вижу одно сообщение для каждого цикла (Level.FINE сообщения отсутствуют).



вопрос



что нужно изменить, чтобы увидеть FINE (,FINER или FINEST) выходной?



обновление (решение)



благодаря ответу Винета Рейнольдса, эта версия работает в соответствии с моими ожиданиями. Он показывает 3xINFO сообщения, & 3xFINE сообщения.



import java.util.logging.*;

class LoggingLevelsBlunder {

public static void main(String[] args) {
Logger logger = Logger.getAnonymousLogger();
// LOG this level to the log
logger.setLevel(Level.FINER);

ConsoleHandler handler = new ConsoleHandler();
// PUBLISH this level
handler.setLevel(Level.FINER);
logger.addHandler(handler);

System.out.println("Logging level is: " + logger.getLevel());
for (int ii=0; ii<3; ii++) {
logger.log(Level.FINE, ii + " " + (ii*ii));
logger.log(Level.INFO, ii + " " + (ii*ii));
}
}
}
574   7  

7 ответов:

регистраторы только регистрируют сообщение, т. е. они создают записи журнала (или запросы на ведение журнала). Они не публикуют сообщения в пункты назначения, о чем заботятся обработчики. Установка уровня регистратора, только вызывает его создать записи журнала, соответствующие этому уровню или выше.

можно использовать ConsoleHandler (Я не мог понять, где ваш выход-система.err или файл, но я бы предположил, что это первый), который по умолчанию равен публикация записей журнала уровня Level.INFO. Вам придется настроить этот обработчик, чтобы публиковать записи журнала уровня Level.FINER и выше, для желаемого результата.

Я бы рекомендовал прочитать Обзор Ведения Журнала Java руководство, чтобы понять основные конструкции. Руководство охватывает разницу между понятием регистратора и обработчика.

редактирование уровня обработчика

1. С помощью Конфигурационный файл

java.утиль.файл свойств журнала (по умолчанию это на JRE_HOME/lib) можно изменить, чтобы изменить уровень по умолчанию ConsoleHandler:

java.util.logging.ConsoleHandler.level = FINER

2. Создание обработчиков во время выполнения

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

Handler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.FINER);
Logger.getAnonymousLogger().addHandler(consoleHandler);

Почему

java.утиль.ведение журнала имеет корневой регистратор, который по умолчанию Level.INFO, и ConsoleHandler прилагается к нему, что также по умолчанию Level.INFO. FINE меньше INFO, так хорошо, что сообщения не отображаются по умолчанию.


Решение 1

создайте регистратор для всего вашего приложения, например, из вашего имени пакета или используйте Logger.getGlobal(), и подключить свой собственный ConsoleLogger к нему. Тогда либо попросите корневой регистратор заткнуться (чтобы избежать дублирования вывода сообщений более высокого уровня), или попросите ваш регистратор не пересылать журналы в корень.

public static final Logger applog = Logger.getGlobal();
...

// Create and set handler
Handler systemOut = new ConsoleHandler();
systemOut.setLevel( Level.ALL );
applog.addHandler( systemOut );
applog.setLevel( Level.ALL );

// Prevent logs from processed by default Console handler.
applog.setUseParentHandlers( false ); // Solution 1
Logger.getLogger("").setLevel( Level.OFF ); // Solution 2

решение 2

кроме того, вы можете опустить панель корневого регистратора.

вы можете установить их кодом:

Logger rootLog = Logger.getLogger("");
rootLog.setLevel( Level.FINE );
rootLog.getHandlers()[0].setLevel( Level.FINE ); // Default console handler

или с файлом конфигурации регистрации, если вы используя это:

.level = FINE
java.util.logging.ConsoleHandler.level = FINE

понизив глобальный уровень, вы можете начните просматривать сообщения из основных библиотек, таких как некоторые компоненты Swing или JavaFX. В этом случае вы можете установить фильтр на корневом регистраторе, чтобы отфильтровать сообщения не из вашей программы.

почему мой журнал java не работает

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

почему

как упоминалось @Sheepy, причина, по которой он не работает, заключается в том, что java.util.logging.Logger имеет корневой регистратор, который по умолчанию Level.INFO и ConsoleHandler прикрепленный к этому корневому регистратору также по умолчанию Level.INFO. Поэтому, чтобы увидеть FINE (,FINER или FINEST) выходной, вам нужно установить значение по умолчанию для корневого регистратора и его ConsoleHandler до Level.FINE следующим образом:

Logger.getLogger("").setLevel(Level.FINE);
Logger.getLogger("").getHandlers()[0].setLevel(Level.FINE);


проблема обновления (решение)

как уже упоминалось @mins, вы будете иметь сообщения, напечатанные дважды на консоли для INFO и выше: сначала анонимным регистратором, затем его родителем, корневым регистратором, который также имеет ConsoleHandler значение INFO по умолчанию. Чтобы отключить корневой регистратор, необходимо добавить следующую строку кода:logger.setUseParentHandlers(false);

есть и другие способы предотвратить обработку журналов консольным обработчиком по умолчанию корневого регистратора, упомянутого @Sheepy, например:

Logger.getLogger("").getHandlers()[0].setLevel( Level.OFF );

но Logger.getLogger("").setLevel( Level.OFF ); не будет работать, потому что он блокирует только сообщение, переданное непосредственно корневому регистратору, а не сообщение от дочернего регистратора. Чтобы проиллюстрировать, как Logger Hierarchy работает, я рисую следующую диаграмму:

enter image description here

public void setLevel(Level newLevel) установите уровень журнала, указав, какие уровни сообщений будут регистрироваться этим регистратором. Уровни сообщений ниже этого значения будут отброшены. Значение уровня Уровень.OFF может использоваться для отключения ведения журнала. Если новый уровень равен null, это означает, что этот узел должен наследовать свой уровень от своего ближайшего предка с определенным (ненулевым) значением уровня.

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

попробовал другие варианты, это может быть правильным

    Logger logger = Logger.getLogger(MyClass.class.getName());        
    Level level = Level.ALL;
    for(Handler h : java.util.logging.Logger.getLogger("").getHandlers())    
        h.setLevel(level);
    logger.setLevel(level);
// this must be shown
    logger.fine("fine");
    logger.info("info");

это решение кажется мне лучше, Что касается ремонтопригодности и дизайна для изменения:

  1. создайте файл свойств журнала, встраивая его в папку проекта ресурсов, чтобы включить в файл jar:

    # Logging
    handlers = java.util.logging.ConsoleHandler
    .level = ALL
    
    # Console Logging
    java.util.logging.ConsoleHandler.level = ALL
    
  2. Загрузить файл свойств из кода:

    public static java.net.URL retrieveURLOfJarResource(String resourceName) {
       return Thread.currentThread().getContextClassLoader().getResource(resourceName);
    }
    
    public synchronized void initializeLogger() {
       try (InputStream is = retrieveURLOfJarResource("logging.properties").openStream()) {
          LogManager.getLogManager().readConfiguration(is);
       } catch (IOException e) {
          // ...
       }
    }
    

Comments

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