Java Logging之JUL系列——Log Levels
JDK自带的日志组件在java.util.logging包中,该组件将日志级别分为如下九种,级别从上到下依次降低,每种级别都对应一个整数值,如下所示:
- OFF(Integer.MAX_VALUE)
- SEVERE(1000)
- WARNING(900)
- INFO(800)
- CONFIG(700)
- FINE(500)
- FINER(400)
- FINEST(300)
- ALL(Integer.MIN_VALUE)
日志级别由java.util.logging.Level
类来表示,级别的作用是用来过滤日志输出的,除此之外,过滤器(Filter)也能起到对日志输出进行过滤的作用,我们后文再详细讨论Filter。
首先我们来看一下JUL组件最常见的用法:
package cn.codecrazy.study;
import java.util.logging.Logger;
public class JavaLogging {
private static final Logger logger = Logger.getLogger(JavaLogging.class.getName());
public static void main(String[] args) {
logger.finest("This is a finest message");
logger.finer("This is a finer message");
logger.fine("This is a fine message");
logger.config("This is a config message");
logger.info("This is an info message");
logger.warning("This is a warning message");
logger.severe("This is a severe message");
}
}
输出如下所示:
八月 08, 2018 9:36:08 下午 cn.codecrazy.study.JavaLogging main
信息: This is an info message
八月 08, 2018 9:36:08 下午 cn.codecrazy.study.JavaLogging main
警告: This is a warning message
八月 08, 2018 9:36:08 下午 cn.codecrazy.study.JavaLogging main
严重: This is a severe message
为什么只输出了info以及info级别以上的信息呢?
以logger.config("This is a config message")
方法为例,该方法内部调用的是logger.log(Level.CONFIG, "This is a config message")
方法,其他的方法同理,都是对Logger.log方法的一种封装,只不过不同的方法传入的日志级别不一样。Logger.log(Level level, String msg)
该方法的实际含义为:比较参数中传入的level和当前Logger对象的level级别,如果参数中传入的level级别高于或等于当前Logger对象的级别,则将message进行输出。底层调用的方法如下:
public void log(Level level, String msg) {
if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
doLog(lr);
}
如果isLoggable方法返回false,则直接return.
public boolean isLoggable(Level level) {
if (level.intValue() < levelValue || levelValue == offValue) {
return false;
}
return true;
}
如果当前logger对象的levelValue为offValue(即Level.OFF级别对应的整数)说明关闭了日志记录功能,不进行输出,或者是传入的日志级别比当前logger的level低,也不进行输出。换句话说就是日志记录器Logger只对级别高于或者等于它自身日志级别的信息进行输出。那么我们可以推测,当前的logger对象的日志级别默认应该就是INFO级别。
我们可以更改一下logger的级别为WARNING:
logger.setLevel(Level.WARNING);
输出如下:
八月 08, 2018 10:19:07 下午 cn.codecrazy.study.JavaLogging main
警告: This is a warning message
八月 08, 2018 10:19:07 下午 cn.codecrazy.study.JavaLogging main
严重: This is a severe message
这次只输出了WARNING以及SEVERE级别的日志信息。说明Level起到了过滤日志输出的作用。实际应用中,当我们调整日志级别的时候,相同的应用程序代码输出的日志会不同。
我们试着把日志级别设置为更低的CONFIG级别,根据我们前面的论述,最终的输出应该是输出CONFIG及其以上级别的日志信息,但实际的输出结果却是:
八月 08, 2018 9:36:08 下午 cn.codecrazy.study.JavaLogging main
信息: This is an info message
八月 08, 2018 9:36:08 下午 cn.codecrazy.study.JavaLogging main
警告: This is a warning message
八月 08, 2018 9:36:08 下午 cn.codecrazy.study.JavaLogging main
严重: This is a severe message
并没有输出CONFIG级别的日志,还是输出的INFO及其以上级别的日志。为什么会这样呢?这是因为不仅Logger有Level的概念,JUL中的另一组件Handler也有Level的概念,Logger对message的输出最终是通过Handler来进行实际操作的,在输出的过程中,Handler组件依然会判断当前需要输出的日志级别跟Handler自身的级别相比是高还是低,只有当前需要输出的日志级别高于或者等于Handler自身的日志级别才会进行输出。
在这里我们的Logger级别设置为了CONFIG,通过logger.config
方法进行输出时,当前需要输出的日志级别为CONFIG,该级别不小于Logger的日志级别,因此不会被过滤,但是该级别小于实际进行输出操作的Handler的级别(默认是INFO),因此不会被该Handler进行实际的输出操作。
关于Handler的详细信息会在后续文章中进行介绍。