为什么没有显示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
(, FINER
或FINEST
)输出,需要改变什么?
更新(解决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/lib
的logging.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.INFO
。 FINE
低于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");