Java 为什么不显示Level.FINE日志消息?
国家:Java 为什么不显示Level.FINE日志消息?,java,logging,java.util.logging,Java,Logging,Java.util.logging,国家: 按降序排列的级别为: 严重(最高值) 警告 INFO CONFIG FINE FINER FINEST(最低值) 来源 问题陈述 我的示例将级别设置为更精细,因此我希望每个循环看到2条消息。相反,我看到每个循环都有一条消息(缺少级别。FINE消息) 问题: 要查看FINE(,FINER或FINEST)输出,需要更改哪些内容 更新(解决方案) 多亏了,这个版本符合我的期望。它显示3条INFO消息和3条FINE消息 import java.util.logging.*; class
按降序排列的级别为:
(最高值)严重
警告
INFO
CONFIG
FINE
FINER
(最低值)FINEST
来源 问题陈述 我的示例将
级别
设置为更精细
,因此我希望每个循环看到2条消息。相反,我看到每个循环都有一条消息(缺少级别。FINE
消息)
问题:
要查看FINE
(,FINER
或FINEST
)输出,需要更改哪些内容
更新(解决方案)
多亏了,这个版本符合我的期望。它显示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));
}
}
}
import java.util.logging.*;
类LoggingLevelsBlunder{
公共静态void main(字符串[]args){
Logger=Logger.getAnonymousLogger();
//将此级别记录到日志中
logger.setLevel(Level.FINER);
ConsoleHandler handler=新的ConsoleHandler();
//发布此级别
handler.setLevel(Level.FINER);
addHandler(handler);
System.out.println(“日志记录级别为:“+logger.getLevel());
对于(int ii=0;ii记录器仅记录消息,即他们创建日志记录(或日志记录请求)。他们不将消息发布到目标,这由处理程序负责。设置记录器的级别只会导致它创建与该级别或更高级别匹配的日志记录
您可能正在使用一个(我无法推断您的输出是System.err还是一个文件,但我假设它是前者),它默认为发布level.INFO
级别的日志记录。您必须配置此处理程序,才能发布level.FINER
或更高级别的日志记录,以获得所需的结果
为了理解底层设计,我建议阅读本指南。本指南涵盖了记录器和处理程序概念之间的区别
编辑处理程序级别
1.使用配置文件
可以修改java.util.logging属性文件(默认情况下,这是JRE_HOME/lib
中的logging.properties
文件),以更改ConsoleHandler的默认级别:
java.util.logging.ConsoleHandler.level = FINER
2.在运行时创建处理程序
不建议这样做,因为这将导致覆盖全局配置。在整个代码库中使用此选项将导致可能无法管理的记录器配置
Handler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.FINER);
Logger.getAnonymousLogger().addHandler(consoleHandler);
提供一个jar文件,该文件将帮助您了解为什么您的登录无法按预期工作。
它为您提供安装了哪些记录器和处理程序、设置了哪些级别以及日志层次结构中的哪个级别的完整转储信息。原因
java.util.logging有一个默认为Level.INFO
的根记录器,以及一个连接到它的控制台句柄,该控制台句柄也默认为Level.INFO
。
FINE
低于INFO
,因此默认情况下不显示FINE消息
解决方案1
为您的整个应用程序创建一个记录器,例如,根据您的软件包名称或用途,并将您自己的ConsoleLogger挂接到该记录器上。
然后要求根日志记录器关闭(以避免重复输出更高级别的消息),或者要求日志记录器关闭根日志记录器
公共静态最终记录器applog=Logger.getGlobal();
...
//创建并设置处理程序
Handler systemOut=新控制台Handler();
systemOut.setLevel(Level.ALL);
addHandler(systemOut);
applog.setLevel(Level.ALL);
//阻止默认控制台处理程序处理日志。
setUseParentHandlers(false);//解决方案1
Logger.getLogger(“”.setLevel(Level.OFF);//解决方案2
解决方案2 或者,您可以降低根记录器的栏 您可以通过代码设置它们:
Logger rootLog=Logger.getLogger(“”);
rootLog.setLevel(Level.FINE);
rootLog.getHandlers()[0].setLevel(Level.FINE);//默认控制台处理程序
或使用日志记录配置文件,如果您是:
.level=FINE
java.util.logging.ConsoleHandler.level=FINE
通过降低全局级别,您可能开始看到来自核心库的消息,例如来自某些Swing或JavaFX组件的消息。
在这种情况下,您可以在根记录器上设置一个,以过滤掉不来自您程序的消息。我发现了实际的问题,但在任何回答中都没有提到:我的一些单元测试导致在同一测试套件中多次运行日志初始化代码,扰乱了后续测试的日志记录。尝试了其他变体s、 这可能是适当的
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");
为什么
正如@Sheepy所提到的,它不起作用的原因是java.util.logging.Logger
有一个默认为Level.INFO
的根记录器,并且附加到该根记录器的ConsoleHandler
也默认为Level.INFO
。因此,为了查看FINE
(,FINER
或FINEST
)输出,您需要将根记录器及其控制台句柄的默认值设置为级别。FINE
如下所示:
Logger.getLogger("").setLevel(Level.FINE);
Logger.getLogger("").getHandlers()[0].setLevel(Level.FINE);
您的更新问题(解决方案)
正如@mins所提到的,您将在控制台上为INFO
和更高版本打印两次消息:首先由匿名记录器打印,然后由其父级打印,根记录器的ConsoleHandler
默认设置为INFO
。要禁用根记录器,您需要添加以下代码行:logger.setUseParEnhandlers(假);
还有其他方法可以防止默认控制台句柄处理日志
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");
Logger.getLogger("").setLevel(Level.FINE);
Logger.getLogger("").getHandlers()[0].setLevel(Level.FINE);
Logger.getLogger("").getHandlers()[0].setLevel( Level.OFF );
# 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) {
// ...
}
}