更改Logger实例的全局设置

Ami*_*hum 41 java logging

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

private final Logger logger = Logger.getLogger(this.getClass().getName());
Run Code Online (Sandbox Code Playgroud)

我想为我的所有类设置一个日志记录级别,并能够更改它(即,将设置放在一个地方).有没有办法做到这一点,除了使用全局Level变量并手动设置每个记录器?

And*_*mas 66

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

-Djava.util.logging.config.file="logging.properties" 
Run Code Online (Sandbox Code Playgroud)

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

在该文件中,包含如下所示的行:

.level= INFO
Run Code Online (Sandbox Code Playgroud)

这将设置全局级别,可以为特定处理程序和记录程序覆盖该级别.例如,可以覆盖特定记录器的级别,如下所示:

 com.xyz.foo.level = SEVERE
Run Code Online (Sandbox Code Playgroud)

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

  • +1这应该是公认的答案,而这个(简单,简洁)的回答应该链接到所有这些问题的java.util.logging以便正确使用Java API来调整的java.util.logging.不知道为什么这个nuggget实际上埋没在java文档中,每个人都需要这样做.就目前而言,仅仅使用slf4j + logback比试图找出jul + logging.properties更容易 (9认同)

mor*_*rja 36

正如Andy 回答的那样,在大多数情况下,您应该使用属性文件和VM参数,因此它独立于您的代码.

但是如果你想出于某种原因以编程方式进行编程(我自己在一个案例中有充分的理由)你也可以像这样访问处理程序:

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

编辑我将setLevel添加到根记录器中,因为searchengine27在他的回答中指出.

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

或者像这样更改过滤器:

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

  • 我同意,使用配置文件是要走的路.只想在问题中询问如何手动显示. (9认同)
  • 是的,对于那些认为这是接受的答案的人:不要这样做.只需更改配置文件中的属性即可.另一个答案应该是"已接受"的答案(即设置java.util.logging.config.file = ...).像这样的代码只会让切换到slf4j/logback更加困难:-) (5认同)
  • 有时您需要以编程方式执行此操作,但它不应该是常态......它应该是一种特殊需求. (2认同)

sea*_*e27 23

所以我并不完全喜欢这里的所有答案,所以我打算参加.

配置文件使用

你在这里看到很多答案,告诉你使用配置文件,因为这是最好的做法.我想以更好的方式解释如何以编程方式执行此操作,但在此之前,我想说我可以看到它们的来源,并且在客观的情绪中,我会稍微启发一下(特别是因为没有人说为什么不好的做法).我实际上想要分享一些人在单独的StackOverflow答案中所说的与编程设置记录器级别有关的问题(为什么Level.FINE记录消息没有显示?):

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

在那个问题上,我认为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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 只是为了澄清,``"`是根记录器,而不是匿名记录器. (3认同)

Bas*_*uga 5

morja 答案的单行 Java 8 方法:

Arrays.stream(LogManager.getLogManager().getLogger("").getHandlers()).forEach(h -> h.setLevel(Level.INFO));
Run Code Online (Sandbox Code Playgroud)