Java Logger层次结构补充

早天看到一遍关于JDK日志层级的文章,原文:

http://tutorials.jenkov.com/java-logging/logger-hierarchy.html

一路被这个文章讲的晕头转向。什么 forward,Passed,propagated等等。

JDK为什么把他设计的那么复杂,今天看一下JDK的代码。发现他测试的结果是对的,但讲法的差强人意。

wKiom1muWV3gwg80AAA3S19K2O0113.png-wh_50

日志结构却如上图树形所示,但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的传递问题,文件讲得太不好理解有两个点:

  1.  accept or reject 只发生在当前logger的filter上,若当前logger无filter,则accept。

  2. 若当前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 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 Loggerhas 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)。

若代码改成:

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

所以很多费解的文章都是有问题的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值