- *** 作系统:Ubuntu 20.04
- JDK:17.0.1
Java自带log功能,用的是JDK标准库中的类java.util.logging.Logger
。下面是一个简单的例子:
package pkg1;
import java.util.logging.*;
public class Test0509 {
public static void main(String[] args) {
Logger logger = Logger.getLogger(Test0509.class.getName());
logger.finest("finest");
logger.finer("finer");
logger.fine("fine");
logger.config("config");
logger.info("info");
logger.warning("warning");
logger.severe("severe");
}
}
运行程序,结果如下:
May 09, 2022 2:57:02 PM pkg1.Test0509 main
INFO: info
May 09, 2022 2:57:02 PM pkg1.Test0509 main
WARNING: warning
May 09, 2022 2:57:02 PM pkg1.Test0509 main
SEVERE: server
可见,默认的log级别是 INFO
,也就是说 INFO
以及更高级别的log会生效。
注:Logger的 info()
等方法都有一个重载方法,参数的类型是 Supplier
,例如:
logger.info("info1" + "info2");
logger.info(() -> "info1" + "info2");
两者功能非常类似,区别在于,前者一定会运行 "info1" + "info2"
,而后者只有在log级别为 INFO
或者更低的时候,才会运行 "info1" + "info2"
,避免了不必要的运算,显然后者性能更好。
现在我们来尝试调整log级别:
......
logger.setLevel(Level.WARNING);
logger.finest("finest");
logger.finer("finer");
logger.fine("fine");
logger.config("config");
logger.info("info");
logger.warning("warning");
logger.severe("severe");
......
运行程序,结果如下:
May 09, 2022 3:01:00 PM pkg1.Test0509 main
WARNING: warning
May 09, 2022 3:01:00 PM pkg1.Test0509 main
SEVERE: server
可见,把Logger的级别调整到 WARNING
之后,只有 WARNING
和 SEVERE
级别的log生效。
接下来把Logger的级别换成 FINER
试试看:
......
logger.setLevel(Level.FINER);
// comment 1
logger.finest("finest");
logger.finer("finer");
logger.fine("fine");
logger.config("config");
logger.info("info");
logger.warning("warning");
logger.severe("severe");
......
运行程序,结果如下:
May 09, 2022 6:56:55 PM pkg1.Test0509_3 main
INFO: info
May 09, 2022 6:56:55 PM pkg1.Test0509_3 main
WARNING: warning
May 09, 2022 6:56:55 PM pkg1.Test0509_3 main
SEVERE: severe
问题来了,为什么还是只有 INFO
以及更高的log级别生效呢?
原因在于,Logger可以有多个Handler,比如下面要提到的 ConsoleHandler
和 FileHandler
。顾名思义,分别把log输出到控制台和文件。默认情况下(参见下面的默认配置文件),是使用 ConsoleHandler
,这就是为什么log默认会输出到命令行。
如果给Logger配置了多个Handler,则多个Handler同时生效,也就是说log可以既输出到控制台,同时也输出到文件。通过文件或者代码,都可以配置Handler。
事实上,Handler也可以设置级别(默认级别也是 INFO
),与Logger的级别相比,最终二者中较高的级别生效。这就解释了为什么把Logger级别设置为 WARNING
生效,而设置为 FINER
却不生效了,因为Handler的级别仍然是 INFO
,二者中 INFO
级别较高,因此 INFO
及以上级别生效。
要使 FINER
级别生效,需要把Handler的级别也设置成 FINER
,在上面的 comment 1
处添加代码:
for (Handler handler : Logger.getLogger("").getHandlers()) {
handler.setLevel(Level.FINER);
}
再次运行程序,结果如下:
May 09, 2022 7:09:44 PM pkg1.Test0509_3 main
FINER: finer
May 09, 2022 7:09:44 PM pkg1.Test0509_3 main
FINE: fine
May 09, 2022 7:09:44 PM pkg1.Test0509_3 main
CONFIG: config
May 09, 2022 7:09:44 PM pkg1.Test0509_3 main
INFO: info
May 09, 2022 7:09:44 PM pkg1.Test0509_3 main
WARNING: warning
May 09, 2022 7:09:44 PM pkg1.Test0509_3 main
SEVERE: severe
可见,这回 Finer
及以上级别生效了。
默认配置文件是 $JAVA_HOME/conf/logging.properties
,里面可以配置各种日志选项,比如:
handlers= java.util.logging.ConsoleHandler
:设置Handler,若有多个Handler(比如FileHandler
),handler之间用,
隔开;.level= INFO
:默认的全局log级别;java.util.logging.FileHandler.pattern = %h/java%u.log
:文件日志的命名,其中%h
表示home目录,%u
表示0、1、2这样的数字;java.util.logging.FileHandler.limit = 50000
:文件日志的大小?java.util.logging.FileHandler.count = 1
:文件日志的数量?java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
:文件日志的格式java.util.logging.ConsoleHandler.level = INFO
:控制台日志的级别java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
:控制台日志的格式- ……
例如:把 java.util.logging.ConsoleHandler.level = INFO
改为 java.util.logging.ConsoleHandler.level = SEVERE
。再次运行程序,结果如下:
May 09, 2022 3:31:25 PM pkg1.Test0509 main
SEVERE: severe
注意:配置文件里Handler的级别为 SEVERE
,而代码里Logger级别设置为 WARNING
,二者相比,级别较高者生效。
如果要使用自定义配置文件,需要在运行程序时,指定 java.util.logging.config.file
选项。比如 java -Djava.util.logging.config.file=myfile
。
最后别忘了还原默认配置文件。
代码配置前面我们已经试过在代码中设置log级别,下面我们再看看其它配置。比如添加一个 FileHandler
:
......
try {
Handler handler = new FileHandler();
// handler.setLevel(Level.INFO);
logger.addHandler(handler);
} catch (IOException e) {
throw new RuntimeException(e);
}
logger.setLevel(Level.WARNING);
logger.finest("finest");
logger.finer("finer");
logger.fine("fine");
logger.config("config");
logger.info("info");
logger.warning("warning");
logger.severe("severe");
......
运行程序,除了命令行输出结果以外,在home目录下生成 java0.log
文件(这是默认的log文件路径和命名),内容如下:
DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
<date>2022-05-09T07:51:05.215198475Zdate>
<millis>1652082665215millis>
<nanos>198475nanos>
<sequence>0sequence>
<logger>pkg1.Test0509logger>
<level>WARNINGlevel>
<class>pkg1.Test0509class>
<method>mainmethod>
<thread>1thread>
<message>warningmessage>
record>
<record>
<date>2022-05-09T07:51:05.265971919Zdate>
<millis>1652082665265millis>
<nanos>971919nanos>
<sequence>1sequence>
<logger>pkg1.Test0509logger>
<level>SEVERElevel>
<class>pkg1.Test0509class>
<method>mainmethod>
<thread>1thread>
<message>severemessage>
record>
log>
可见,对于log文件和命令行log,都是 WARNING
和 SEVERE
级别的log生效,只不过两种log的格式不同。
如果要指定文件路径和文件名,只需在创建 FileHandler
时指定,比如:
Handler handler = new FileHandler("aaa.log");
现在运行程序,就会在当前目录下生成 aaa.log
文件。注意,在本例中,当前目录指的是项目的根目录。
注意代码中被注释那一行。如果Handler没有设置级别,默认级别是 INFO
,与Logger级别 WARNING
相比,取较高的 WARNING
。如果设置了级别,则二者中级别较高者生效:
handler.setLevel(Level.SEVERE);
:Handler中SEVERE
级别生效;handler.setLevel(Level.INFO);
:Logger中WARNING
级别生效;
- https://docs.oracle.com/en/java/javase/17/docs/api/java.logging/java/util/logging/Logger.html
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)