早天看到一遍关于JDK日志层级的文章,原文:
http://tutorials.jenkov.com/java-logging/logger-hierarchy.html
一路被这个文章讲的晕头转向。什么 forward,Passed,propagated等等。
JDK为什么把他设计的那么复杂,今天看一下JDK的代码。发现他测试的结果是对的,但讲法的差强人意。
日志结构却如上图树形所示,但Logger之间的父子关系是通过单独的索引结构表示的。如上图红色线表示logger(com.jenkoe.web)的父logger为rootlogger,在寻祖的过程中,中间结点若是虚结点,由直接跳过。这就是文件所说的:
if you do create a Logger
like this:
Logger logger = Logger.getLogger("com.jenkov.web");
... and call getParent()
method, you will get the Logger
with the name "".
一旦中间的结点有值(由虚变实)需要更新其孩子结点的父索引(具体可看LogContext.addLocalLoader源码)。
再说Filter的传递问题,文件讲得太不好理解有两个点:
accept or reject 只发生在当前logger的filter上,若当前logger无filter,则accept。
若当前logger accept这个日志,则传播到上层logger,一直到根。
太晦涩,看代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public
void
log(LogRecord record) {
if
(!isLoggable(record.getLevel())) {
return
;
}
Filter theFilter = filter;
if
(theFilter !=
null
&& !theFilter.isLoggable(record)) {
return
;
}
// Post the LogRecord to all our Handlers, and then to
// our parents' handlers, all the way up the tree.
Logger logger =
this
;
while
(logger !=
null
) {
final
Handler[] loggerHandlers = isSystemLogger
? logger.accessCheckedHandlers()
: logger.getHandlers();
for
(Handler handler : loggerHandlers) {
handler.publish(record);
}
final
boolean
useParentHdls = isSystemLogger
? logger.useParentHandlers
: logger.getUseParentHandlers();
if
(!useParentHdls) {
break
;
}
logger = isSystemLogger ? logger.parent : logger.getParent();
}
}
|
只用调用当前logger的filter,则所谓的传播是useParentHandler属性在起做作用,若为true,则递归调用祖辈logger的Handler,没有父logger的filter什么事。
在下面关于日志级别的问题,正如上面的代码。只在当前logger里进行了级别检查, 也没传播与否的说法。
文中:
Logger logger = Logger.getLogger(""); Logger logger1 = Logger.getLogger("1"); Logger logger1_2 = Logger.getLogger("1.2"); logger1 .setLevel(Level.WARNING); logger1_2.setLevel(Level.INFO); logger .info("msg:"); logger1 .info("msg: 1"); logger1_2 .info("msg: 1.2");
The result of this code is that the INFO
message logged on the bottom Logger
(named 1.2
) is now logged, but it is still not propagated up the hierarchy. Well, it is, but the middle Logger
filters it out, because the middle Logger
has a log level of WARNING
set. Thus, the message is not logged by the middle Logger
nor propagated up the hierarchy.
不知道作者是否代码粘错了。这里没有propagated, 并不是middle Logger的level问题,而是因为 middle
Logger和
bottom Logger
都没有指定handler。最后全都传导到Root logger(它有默认的handler)。
若代码改成:
1
2
3
4
5
6
7
8
9
10
11
12
|
Logger logger = Logger.getLogger(
""
);
Logger logger1 = Logger.getLogger(
"1"
);
Logger logger1_2 = Logger.getLogger(
"1.2"
);
logger1 .addHandler(
new
ConsoleHandler());
logger1_2 .addHandler(
new
ConsoleHandler());
logger1 .setLevel(Level.WARNING);
logger1_2.setLevel(Level.INFO);
logger .info(
"msg:"
);
logger1 .info(
"msg: 1"
);
logger1_2 .info(
"msg: 1.2"
);
|
结果就是:
1
2
3
4
5
6
7
8
|
九月 05, 2017 4:29:15 下午 java.util.logging.LogManager$RootLogger log
信息: msg:
九月 05, 2017 4:29:15 下午 guojje.SAPITest main
信息: msg: 1.2
九月 05, 2017 4:29:15 下午 guojje.SAPITest main
信息: msg: 1.2
九月 05, 2017 4:29:15 下午 guojje.SAPITest main
信息: msg: 1.2
|
所以很多费解的文章都是有问题的。
本文转自 anranran 51CTO博客,原文链接:http://blog.51cto.com/guojuanjun/1673879