And*_*son 109 java logging java.util.logging
状态的JavaDocsjava.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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
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 . . .
Run Code Online (Sandbox Code Playgroud)
我的示例设置为Level
to FINER
,所以我期望每个循环看到2条消息.相反,我看到每个循环都有一条消息(Level.FINE
消息丢失).
需要改变什么才能看到FINE
(FINER
或FINEST
)输出?
感谢Vineet Reynolds的回答,这个版本符合我的期望.它显示3x INFO
消息和3x 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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
Vin*_*lds 121
记录器仅记录消息,即它们创建日志记录(或记录请求).它们不会将消息发布到目标,这由处理程序负责.设置记录器的级别只会使其创建匹配该级别或更高级别的日志记录.
您可能正在使用ConsoleHandler
(我无法推断您的输出是System.err或文件的位置,但我认为它是前者),默认为发布级别的日志记录Level.INFO
.您必须配置此处理程序,以发布级别Level.FINER
和更高级别的日志记录,以获得所需的结果.
我建议阅读Java Logging Overview指南,以了解底层设计.该指南介绍了Logger和Handler概念之间的区别.
编辑处理程序级别
1.使用配置文件
可以修改java.util.logging属性文件(默认情况下,这是logging.properties
文件JRE_HOME/lib
),以更改ConsoleHandler的默认级别:
java.util.logging.ConsoleHandler.level = FINER
Run Code Online (Sandbox Code Playgroud)
2.在运行时创建处理程序
建议不要这样做,因为它会导致覆盖全局配置.在整个代码库中使用它将导致可能无法管理的记录器配置.
Handler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.FINER);
Logger.getAnonymousLogger().addHandler(consoleHandler);
Run Code Online (Sandbox Code Playgroud)
She*_*epy 25
为什么
java.util.logging有一个默认的根记录器Level.INFO
,以及一个默认连接的ConsoleHandler Level.INFO
.
FINE
低于INFO
,因此默认情况下不显示精细消息.
解决方案1
为整个应用程序创建一个记录器,例如从您的包名或使用Logger.getGlobal()
,并将您自己的ConsoleLogger挂钩到它.然后要求root logger关闭(以避免重复输出更高级别的消息),或要求您的记录器不将日志转发到root.
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
Run Code Online (Sandbox Code Playgroud)
解决方案2
或者,您可以降低根记录器的栏.
您可以通过代码设置它们:
Logger rootLog = Logger.getLogger("");
rootLog.setLevel( Level.FINE );
rootLog.getHandlers()[0].setLevel( Level.FINE ); // Default console handler
Run Code Online (Sandbox Code Playgroud)
或者使用日志配置文件,如果您使用它:
.level = FINE
java.util.logging.ConsoleHandler.level = FINE
Run Code Online (Sandbox Code Playgroud)
通过降低全局级别,您可能会开始看到来自核心库的消息,例如来自某些Swing或JavaFX组件的消息.在这种情况下,您可以在根记录器上设置过滤器,以过滤掉不是来自程序的消息.
为什么
正如@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);
Run Code Online (Sandbox Code Playgroud)
你的更新问题(解决方案)
正如@mins 所提到的,您将在控制台上为INFO
及以上打印两次消息:首先由匿名记录器打印,然后由其父记录器,默认情况下也ConsoleHandler
设置为的根记录器INFO
。要禁用根记录器,您需要添加以下代码行:logger.setUseParentHandlers(false);
还有其他方法可以防止日志被@Sheepy 提到的根记录器的默认控制台处理程序处理,例如:
Logger.getLogger("").getHandlers()[0].setLevel( Level.OFF );
Run Code Online (Sandbox Code Playgroud)
但Logger.getLogger("").setLevel( Level.OFF );
不会工作,因为它只阻止直接传递给根记录器的消息,而不是来自子记录器的消息。为了说明它是如何Logger Hierarchy
工作的,我画了下图:
public void setLevel(Level newLevel)
设置日志级别,指定此记录器将记录哪些消息级别。低于此值的消息级别将被丢弃。级别值 Level.OFF 可用于关闭日志记录。如果新级别为空,则意味着此节点应从其最近的祖先继承其级别,并具有特定(非空)级别值。