Почему такой уровень.Штраф регистрации сообщений не отображается?
The JavaDocs для java.util.logging.Level состояние:
уровни в порядке убывания являются:
SEVERE(максимальное значение)WARNINGINFOCONFIGFINEFINER
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));
}
}
}
7 ответов:
регистраторы только регистрируют сообщение, т. е. они создают записи журнала (или запросы на ведение журнала). Они не публикуют сообщения в пункты назначения, о чем заботятся обработчики. Установка уровня регистратора, только вызывает его создать записи журнала, соответствующие этому уровню или выше.
можно использовать
ConsoleHandler(Я не мог понять, где ваш выход-система.err или файл, но я бы предположил, что это первый), который по умолчанию равен публикация записей журнала уровняLevel.INFO. Вам придется настроить этот обработчик, чтобы публиковать записи журнала уровняLevel.FINERи выше, для желаемого результата.Я бы рекомендовал прочитать Обзор Ведения Журнала Java руководство, чтобы понять основные конструкции. Руководство охватывает разницу между понятием регистратора и обработчика.
редактирование уровня обработчика
1. С помощью Конфигурационный файл
java.утиль.файл свойств журнала (по умолчанию это на
JRE_HOME/lib) можно изменить, чтобы изменить уровень по умолчанию ConsoleHandler:java.util.logging.ConsoleHandler.level = FINER2. Создание обработчиков во время выполнения
это не рекомендуется, поскольку это приведет к переопределению глобальной конфигурации. Использование этого во всей базе кода приведет к возможному неуправляемому регистратору конфигурация.
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работает, я рисую следующую диаграмму:
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");
это решение кажется мне лучше, Что касается ремонтопригодности и дизайна для изменения:
создайте файл свойств журнала, встраивая его в папку проекта ресурсов, чтобы включить в файл jar:
# Logging handlers = java.util.logging.ConsoleHandler .level = ALL # Console Logging java.util.logging.ConsoleHandler.level = ALLЗагрузить файл свойств из кода:
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