Spring Boot日志之Logback(四)—— 日志等级继承

人盡茶涼 提交于 2020-02-28 08:52:07

在日常的开发中,Logback配置文件中一般都会定义多个 logger,那它们之间互相的关系又是什么呢?

命令层次结构

首先声明一下 logger 命令层次结构:

如果一个 logger 的名字加上一个 . 作为另一个 logger 名字的前缀,那么该 logger 就是另一个 logger 的祖先。如果一个 logger 与另一个 logger 之间没有其它的 logger ,则该 logger 就是另一个 logger 的父级。

这段话,可能比较抽象,那么举个例子来说:

<logger name="x" level="DEBUG"/>
<logger name="x.y" level="DEBUG"/>
<logger name="x.y.z" level="DEBUG"/>

例子中,定义了 xx.yx.y.z 三个 logger,其中 xx.yx.y.z 的祖先,但是由于 xx.y 之间不存在其它的 logger,所以 x 也是 x.y 的父级。

PS: 这里需要强调一下,代码中创建的 logger 和配置文件中定义的 logger 是相同的,如下面定义了名为 x.y.z 的 logger,和上面声明里的 x.y.z 相同:

private static Logger logger = LoggerFactory.getLogger("x.y.z");

等级继承

配置文件中,logger 的 level 属性不是必选参数,此外代码中创建时也没设置 logger 的等级,那么这些 logger 的等级又是啥呢?

如果一个给定的 logger 没有指定一个等级,那么它就会继承离它最近的一个祖先的等级。

在举例讲解之前,先声明一下,<root> 也属于 logger,只不过它是特殊的 logger,是根 logger,是所有 logger 的祖先。如果它未声明等级,那么会有个默认等级 DEBUG。接下来用表格来展示:

logger 的名字 指定的层级 有效层级
root DEBUG DEBUG
A none DEBUG
A.B INFO INFO
A.B.C none INFO
A.B.C.D ERROR ERROR
X INFO INFO
X.Y DEBUG DEBUG
X.Y.Z WARN WARN

很明显:

  • root 为 DEBUG,而 A 未指定,所以 A 继承 root 的 DEBUG,为 DEBUG;
  • A 为 DEBUG,而 A.B 指定了 INFO,所以 A.B 为 INFO;
  • A.B 为 INFO,而 A.B.C 未指定,所以 A.B.C 继承 A.B 的 INFO,为 INFO;
  • A.B.C 为 INFO,而 A.B.C.D 指定了 ERROR,所以 A.B.C.D 为 ERROR;
  • root 为 DEBUG,而 X 指定了 INFO,所以 X 为 INFO;
  • X 为 INFO,而 X.Y 指定了 DEBUG,所以 X.Y 为 DEBUG;
  • X.Y 为 DEBUG,而 X.Y.Z 指定了 WARN,所以 X.Y.Z 为 WARN。

appender 的叠加性

当定义完了 logger,需要再定义日志输出组件 appender,但是并不是每个 logger 会显示的声明日志输出组件 appender,那么日志输出组件 appender 是如何在 logger 之间叠加继承的呢?

首先,先定义两个 <appender>

<appender name="CONSOLE1" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%-4relative \[%thread\] %-5level %logger{35} - %msg %n</pattern>
        <charset>UTF-8</charset>
    </encoder>
</appender>

<appender name="CONSOLE2" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%-4relative \[%thread\] %-5level %logger{35} - %msg %n</pattern>
        <charset>UTF-8</charset>
    </encoder>
</appender>

这两个名叫 CONSOLE1CONSOLE2appender 是两个单独的组件,两者功能相同,皆是在控制台根据一定的格式打印日志。

同时,定义三个 logger,具体如下:

<logger name="x" level="DEBUG"/>
<logger name="x.y" level="WARN"/>
<logger name="x.y.z" level="INFO"/>

现在,把 CONSOLE1appender 添加到名为 xlogger 上,由于默认 additivity 为 true,所以 CONSOLE1appender 会被 x.yx.y.z 继承叠加,所以如果 x.y.z 如果有日志输出,能通过 CONSOLE1appender 进行输出,同理 x.y 的日志也一样。

接着,把 CONSOLE1CONSOLE2appender 添加到名为 x.ylogger 上,由于继承叠加了 CONSOLE1appender,所以这个 logger 具有三个 appender。系统不会对 appender 进行去重操作,所以如果有日志输出的话,日志会在 CONSOLE1 的 appender 中输出两遍。

如果想要防止在同一个 appender 多次输出的问题,可以通过设置 additivity 为 false 进行处理。合理的设置 appenderlogger 的关系,防止日志重复输出,是关键。

PS:以上内容均参考 Logback中文网

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!