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

| Doc0ѭ状态的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
条消息)。 题 为了看到
FINE
(,
FINER
FINEST
)输出,需要进行哪些更改? 更新(解决方案) 感谢Vineet Reynolds的回答,该版本可以按照我的期望工作。它显示3 x
INFO
消息和3 x
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));
        }
    }
}
    
已邀请:
        记录器仅记录消息,即它们创建日志记录(或记录请求)。它们不会将消息发布到目的地,这由处理程序负责。设置记录器的级别只会导致它创建与该级别或更高级别匹配的日志记录。 您可能正在使用ѭ19(我无法推断您的输出是System.err还是文件,但我认为它是前者),默认情况下将发布级别为ѭ20的日志记录。您必须配置此处理程序,才能发布级别为
Level.FINER
或更高的日志记录,以获得所需的结果。 我建议阅读《 Java日志记录概述》指南,以了解基础设计。该指南涵盖了Logger和Handler概念之间的区别。 编辑处理程序级别 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);
    
        为什么 java.util.logging有一个默认为
Level.INFO
的根记录器,并附带了一个默认为
Level.INFO
的ConsoleHandler。
FINE
低于
INFO
,因此默认情况下不会显示精细消息。 解决方案1 为您的整个应用程序创建一个记录器,例如从您的软件包名称中输入,或使用
Logger.getGlobal()
,然后将您自己的ConsoleLogger挂接到该软件包上。 然后,要么要求root记录器关闭(以避免重复输出更高级别的消息),要么让记录器不要将日志转发到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
解决方案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
)输出,需要将根记录器的默认值及其and19ѭ设置为
Level.FINE
,如下所示:
Logger.getLogger(\"\").setLevel(Level.FINE);
Logger.getLogger(\"\").getHandlers()[0].setLevel(Level.FINE);
您的更新问题(解决方案) 如@mins所述,您将在控制台上为
INFO
及更高版本两次打印消息:首先由匿名记录器,然后由其父记录器,即根记录器,根记录器默认情况下也将
ConsoleHandler
设置为
INFO
。要禁用root logger,您需要添加以下代码行:
logger.setUseParentHandlers(false);
还有其他方法可以防止@Sheepy提到的root记录程序的默认控制台处理程序处理日志,例如:
Logger.getLogger(\"\").getHandlers()[0].setLevel( Level.OFF );
但是
Logger.getLogger(\"\").setLevel( Level.OFF );
行不通,因为它仅阻止直接传递到根记录器的消息,而不阻止来自子记录器的消息。为了说明ѭ50的工作原理,我画了下图:
public void setLevel(Level newLevel)
设置日志级别,指定此记录器将记录哪些消息级别。低于此值的消息级别将被丢弃。级别值Level.OFF可用于关闭日志记录。如果新级别为null,则表示此节点应使用特定的(非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) {
      // ...
   }
}
    

要回复问题请先登录注册