为什么没有显示Level.FINE日志消息?

java.util.logging.Level状态的JavaDocs :


水平按降序排列:

  • 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消息( Level.FINE消息丢失)。

为了看到FINE (, FINERFINEST )输出,需要改变什么?

更新(解决scheme)

感谢Viney Reynolds的回答 ,这个版本符合我的预期。 它显示3个INFO消息和3个FINE消息。

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

logging器只logging消息,即他们创build日志logging(或logging请求)。 他们不会将消息发布到由处理程序处理的目的地。 设置logging器的级别只会使其创build匹配该级别或更高级别的日志logging。

您可能正在使用ConsoleHandler (我无法推断出您的输出是System.err还是一个文件,但我会假设它是前者),默认情况下是发布Level.INFO级别的日志logging。 您将必须configuration此处理程序,以发布级别Level.FINER和更高级别的日志logging,以获得所需的结果。

我build议阅读Java日志概述指南,以了解底层devise。 指南介绍了Logger和Handler的概念之间的区别。

编辑处理程序级别

1.使用configuration文件

java.util.logging属性文件(默认情况下,这是JRE_HOME/liblogging.properties文件)可以修改,以更改ConsoleHandler的默认级别:

 java.util.logging.ConsoleHandler.level = FINER 

2.在运行时创build处理程序

这不被推荐,因为它会导致覆盖全局configuration。 在整个代码库中使用这将导致可能无法pipe理的logging器configuration。

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

为什么

java.util.logging有一个默认为Level.INFO的根logging器和一个连接到它的ConsoleHandler,它也默认为Level.INFOFINE低于INFO ,所以默认情况下不会显示细小的信息。


解决scheme1

为您的整个应用程序创build一个logging器,例如从您的包名称或使用Logger.getGlobal() ,并挂钩您自己的ConsoleLogger。 然后或者要求根logging器closures(以避免重复输出更高级别的消息),或者要求logging器不要将日志转发到根。

 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 

解决scheme2

或者,您可以降低根logging器的栏。

你可以通过代码设置它们:

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

或者使用日志configuration文件,如果您正在使用它 :

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

通过降低全局级别,您可以开始查看来自核心库的消息,例如某些Swing或JavaFX组件。 在这种情况下,您可以在根logging器上设置一个filter来过滤不是来自程序的消息。

为什么我的Java日志logging不工作

提供了一个jar文件,可以帮助你找出为什么你的日志不能按预期工作。 它给你一个完整的转储logging器和处理程序已安装,什么级别设置和在日志层次结构中的哪个级别。

我发现我的实际问题,并没有在任何答案中提到:我的一些unit testing导致日志初始化代码在同一个testing套件中运行多次,混淆了以后的testing日志logging。

试过其他变种,这可能是适当的

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