【问题标题】:Change global setting for Logger instances更改 Logger 实例的全局设置
【发布时间】:2011-06-10 14:19:11
【问题描述】:

我使用java.util.logging.Logger 作为我的应用程序的日志引擎。每个类都使用自己的记录器,即每个类都有:

private final Logger logger = Logger.getLogger(this.getClass().getName());

我想为我的所有课程设置一个日志记录级别,并能够更改它(即,将设置放在一个地方)。除了使用全局 Level 变量并手动设置每个记录器之外,还有其他方法吗?

【问题讨论】:

    标签: java logging


    【解决方案1】:

    一种简单的方法是使用日志属性文件,通过包含此 VM 参数:

    -Djava.util.logging.config.file="logging.properties" 
    

    其中“logging.properties”是包含日志记录配置的文件的路径。对于相对路径,进程的工作目录很重要。

    在该文件中,包含如下一行:

    .level= INFO
    

    这设置了全局级别,可以为特定的处理程序和记录器覆盖。例如,可以像这样覆盖特定记录器的级别:

     com.xyz.foo.level = SEVERE
    

    您可以从 jre6\lib\logging.properties 获取日志记录属性文件的模板。

    【讨论】:

    • +1 这应该是公认的答案,并且这个(简单、简洁的)答案应该与 S.O. 中的所有 java.util.logging 问题相关联。错误地使用 Java API 来调整 java.util.logging。不知道为什么这个块实际上埋在 java 文档中,每个人都需要这样做。就目前而言,仅使用 slf4j+logback 比尝试找出 jul+logging.properties 更容易
    • nb:如果您有设置级别的处理程序,您还必须设置/重置这些,否则它们将覆盖您的其他日志记录级别。如果优先规则令人困惑,您可以同时设置:java.util.logging.FileHandler.level=FINE + com.my.package.level=FINE
    • 我在我的日志管理器实例中发现了com.xyz.foo.level,这使我找到了jre/lib/logging.properties,并且-Djava.util.logging.config.file="WEB-INF/classes/logging.properties" 是必需的,因为JVM 不会费心搜索类路径。
    • 有趣的是,每个记录器级别的属性(.level[package].level)在 Java 8 中对我不起作用。所有其他属性都按预期工作。我必须明确添加每个处理程序级别的属性 ([handler].level)。
    • @AndyThomas 有没有办法在没有 JVM 参数的情况下做到这一点?
    【解决方案2】:

    作为 Andy answered,在大多数情况下,您应该使用属性文件和 VM 参数,因此它独立于您的代码。

    但是,如果您出于某种原因想要以编程方式进行(我自己在一种情况下有充分的理由),您也可以像这样访问处理程序:

    Logger rootLogger = LogManager.getLogManager().getLogger("");
    rootLogger.setLevel(Level.INFO);
    for (Handler h : rootLogger.getHandlers()) {
        h.setLevel(Level.INFO);
    }
    

    编辑我将 setLevel 添加到根记录器中,正如 searchengine27 在他的 answer 中指出的那样。

    处理程序是您通过属性或以编程方式设置的文件或控制台处理程序。

    或者像这样更改过滤器:

    Logger rootLogger = LogManager.getLogManager().getLogger("");
    rootLogger.setFilter(new Filter() {
        @Override
        public boolean isLoggable(LogRecord record) {
                return "something".equals(record.getLoggerName());
        }
    });
    

    【讨论】:

    • 是的,对于任何认为这是公认答案的人:不要这样做。只需更改配置文件中的属性。另一个答案应该是“接受”的答案(即设置 java.util.logging.config.file=...)。这样的代码只会让切换到 slf4j/logback 变得更加困难:-)
    • 我同意,使用配置文件是要走的路。只是想展示如何手动执行此操作,因为这是问题中提出的。
    • 有时您需要以编程方式执行此操作,但这不应该成为常态......这应该是一种特殊的需求。
    • 我动态更改日志记录的用例是在 Tomcat 应用程序中,其中 99% 的时间我不需要除 CRITICAL 之外的任何日志记录,但当某些事情无法正常工作时,我想将级别调高(调低?)INFO 以查看我的所有日​​志消息。
    【解决方案3】:

    所以我并不完全喜欢这里的所有答案,所以我要插话。

    配置文件使用

    您在这里看到很多答案告诉您使用配置文件,因为这是最佳实践。我想更好地解释如何以编程方式执行此操作,但在此之前,我想说我可以看到它们来自哪里,并且本着客观的心情,我会启发你一点(尤其是因为没有人说 为什么这是不好的做法)。我实际上想分享某人在另一个 StackOverflow 答案中所说的与以编程方式设置记录器级别有关的内容 (Why are the Level.FINE logging messages not showing?):

    不建议这样做,因为它会导致覆盖全局配置。在整个代码库中使用它可能会导致无法管理的记录器配置。

    关于这一点,我认为 Andy Thomas 有一个很好的答案,即不以非编程方式进行。

    以编程方式设置关卡

    话虽如此,我想更详细地介绍一下以编程方式进行操作,因为我认为它有其用途。

    想象一个场景,您正在使用命令行界面编写一些东西,并且您可以选择指定执行的详细程度,甚至可以指定执行的位置(如在动态日志文件中)。我可能弄错了,但您可能不想在 .conf 文件中静态地执行此操作。特别是如果您不想让您的用户群负责在配置文件中设置这些内容(无论出于何种原因)。然而,这是以上述报价为代价的。这是一个如何以编程方式执行此操作的示例,将所有现有处理程序保持在它们已经处于的任何级别,并且只有 FileHandler 假定新级别:

    public static void setDebugLevel(Level newLvl) {
        Logger rootLogger = LogManager.getLogManager().getLogger("");
        Handler[] handlers = rootLogger.getHandlers();
        rootLogger.setLevel(newLvl);
        for (Handler h : handlers) {
            if(h instanceof FileHandler)
                h.setLevel(newLvl);
        }
    }
    

    我想对此进行扩展,特别是出于一个原因。以编程方式执行此操作时,您只需确保为记录器处理程序设置级别。它的工作方式是检查请求是否对于记录器来说太低,如果是,它将丢弃它。然后处理程序具有相同的检查,因此您需要确保记录器和处理程序都设置为您想要的级别。

    【讨论】:

    • 另外,如果您正在构建桌面摇摆或 fx 应用程序。您将希望动态设置日志记录以获取尽可能多的信息。
    • 澄清一下,"" 是根记录器,而不是匿名记录器。
    • 你是对的。我更新了代码 sn-p 中的变量名,使其更清晰。
    • 赞成这一点,强调您为 记录器和处理程序设置了级别
    【解决方案4】:

    morja's answer 的单行 Java 8 方法:

    Arrays.stream(LogManager.getLogManager().getLogger("").getHandlers()).forEach(h -> h.setLevel(Level.INFO));
    

    【讨论】:

      【解决方案5】:

      JUL(java.util.logging) 是 jvm 中的 java 默认记录器。

      Java Logging Technology--see Overview

      所以你可能会发现C:\Program Files\Java\jre1.8.0_221\lib\logging.properties中已经有一个默认配置文件

      我建议您在项目下创建一个新的配置文件以覆盖默认设置,请执行以下操作:

      配置文件名,logging.properties,所有日志级别都可以在Class Level找到

      handlers= java.util.logging.ConsoleHandler
      .level= INFO
      java.util.logging.ConsoleHandler.level = ALL
      java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
      java.util.logging.SimpleFormatter.format= [%1$tF %1$tT] [%4$-7s] %5$s %n
      
      # your specific logger level
      com.xyz.foo.level = SEVERE
      

      然后添加 jvm 选项以启用配置

      java -Djava.util.logging.config.file="logging.properties" -Duser.country=CN -Duser.language=en
      

      user.countryuser.language 可能会影响日志消息本地化

      【讨论】:

      • 我喜欢这个答案
      猜你喜欢
      • 1970-01-01
      • 2020-08-08
      • 1970-01-01
      • 1970-01-01
      • 2014-10-19
      • 1970-01-01
      • 1970-01-01
      • 2020-04-18
      • 1970-01-01
      相关资源
      最近更新 更多