关于Logger的结构
2015-07-13 18:13
946 查看
早天看到一遍关于JDK日志层级的文章,原文:
http://tutorials.jenkov.com/java-logging/logger-hierarchy.html
一路被这个文章讲的晕头转向。什么 forward,Passed,propagated等等。
JDK为什么把他设计的那么复杂,今天看一下JDK的代码。发现他测试的结果是对的,但讲法的差强人意。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202007/03/99c1426db9a58c79f21441d87dd57524.png)
日志结构却如上图树形所示,但Logger之间的父子关系是通过单独的索引结构表示的。如上图红色线表示logger(com.jenkoe.web)的父logger为rootlogger,在寻祖的过程中,中间结点若是虚结点,由直接跳过。这就是文件所说的:
if you do create a
再说Filter的传递问题,文件讲得太不好理解有两个点:
accept or reject 只发生在当前logger的filter上,若当前logger无filter,则accept。
若当前logger accept这个日志,则传播到上层logger,一直到根。
太晦涩,看代码:
在下面关于日志级别的问题,正如上面的代码。只在当前logger里进行了级别检查, 也没传播与否的说法。
文中:
不知道作者是否代码粘错了。这里没有propagated, 并不是middle
http://tutorials.jenkov.com/java-logging/logger-hierarchy.html
一路被这个文章讲的晕头转向。什么 forward,Passed,propagated等等。
JDK为什么把他设计的那么复杂,今天看一下JDK的代码。发现他测试的结果是对的,但讲法的差强人意。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202007/03/99c1426db9a58c79f21441d87dd57524.png)
日志结构却如上图树形所示,但Logger之间的父子关系是通过单独的索引结构表示的。如上图红色线表示logger(com.jenkoe.web)的父logger为rootlogger,在寻祖的过程中,中间结点若是虚结点,由直接跳过。这就是文件所说的:
if you do create a
Loggerlike this:
Logger logger = Logger.getLogger("com.jenkov.web");... and call
getParent()method, you will get the
Loggerwith the name
"".一旦中间的结点有值(由虚变实)需要更新其孩子结点的父索引(具体可看LogContext.addLocalLoader源码)。
再说Filter的传递问题,文件讲得太不好理解有两个点:
accept or reject 只发生在当前logger的filter上,若当前logger无filter,则accept。
若当前logger accept这个日志,则传播到上层logger,一直到根。
太晦涩,看代码:
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
INFOmessage 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
Loggerfilters it out, because the middle
Loggerhas a log level of
WARNINGset. Thus, the message is not logged by the middle
Loggernor propagated up the hierarchy.
不知道作者是否代码粘错了。这里没有propagated, 并不是middle
Logger的level问题,而是因为 middle Logger和bottom
Logger都没有指定handler。最后全都传导到Root logger(它有默认的handler)。
若代码改成:
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");结果就是:
九月 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所以很多费解的文章都是有问题的。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- jQuery plugin items filter
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树