Logback XML 基础配置详解

XML 配置文件的基本结构:以 <configuration> 开头,后面有零个或多个 <appender> 元素,有零个或多个 <logger> 元素,有最多一个 <root> 元素。

1. <configuration>

根节点 <configuration> 包含以下三个属性:

  • scan :当此属性设置为 true 时,配置文件如果发生改变将被重新加载,默认值为 true。
  • scanPeriod :设置监测配置文件是否有修改的时间间隔,默认为一分钟,如果没有给出时间单位则默认为毫秒。当 scan 为 true 时,此属性生效。
  • debug :当此属性设置为 true 时,将打印出 Logback 内部日志信息,实时查看 Logback 运行状态,默认值为 false。
1
2
3
<configuration scan="true" scanPeriod="60 seconds" debug="false"> 
...省略其余部分...
</configuration>

2. <contextName>

子节点 <contextName> 用来设置上下文名称,每个 logger 都关联到上下文,默认上下文名称为 default。可以使用该元素设置成其他名称,用于区分不同应用程序。

1
2
3
4
<configuration scan="true" scanPeriod="60 seconds" debug="false"> 
<contextName>demo</contextName>
...省略其余部分...
</configuration>

3. <property>

子节点 <property> 用来定义变量,有两个属性 name 和 value,可以通过 「 ${} 」在 logger 上下文中使用变量。

1
2
3
4
5
6
<configuration scan="true" scanPeriod="60 seconds" debug="false"> 
<contextName>demo</contextName>
<property name="log.root" value="./logs"/>
<property name="log.pattern" value="[%d{'MM-dd HH:mm:ss,SSS',GMT+8:00}] %level [%thread] %logger{0}[%line] - %msg%n"/>
...省略其余部分...
</configuration>

4. <appender>

子节点 <appender> 是负责写日志的组件,有两个必要属性 name 和 class。

  • name :指定 appender 名称
  • class :指定 appender 的全限定类名

下面介绍几种常用的类型:

4.1 ConsoleAppender

ConsoleAppender 的作用是将日志输出到控制台

1
2
3
4
5
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>

<encoder> 表示对日志进行格式化,是 0.9.19 版本之后引进的,以前的版本使用 <layout>,前者是目前官方推荐的。它负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输入流。目前 PatternLayoutEncoder 是唯一有用的且默认的 encoder,有一个 <pattern> 节点用来设置日志的格式,使用「 % + 转换符 」的方式。

常用转换符 描述
date{pattern} / d{pattern} 输出时间格式,模式语法与 java.text.SimpleDateFormat 兼容
level / le / p 输出日志级别
thread / t 输出生成日志的线程名称
logger{length} / lo{length} / c{length} 输出日志的 logger 名称,length 可缩短名称,不输入表示输出完整全限定类名,输入 0 表示只输出类名,输入其他数字表示在保证输出包路径首字母及类名的前提下根据剩余 length 的值是否大于从右向左的完整目录名长度决定输出首字母还是完整目录名
line / L 输出执行日志的行号
message / msg / m 输出日志消息
n 换行符
-N 从左到右显示 N 个字符宽度
4.2 FileAppender

FileAppender 的作用是将日志输出到文件中

1
2
3
4
5
6
7
<appender name="FILE" class="ch.qos.logback.core.FileAppender">  
<file>${log.root}/demo.log</file>
<append>true</append>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>

子节点 描述
<file> 表示写入的文件名,可以是相对路径也可以是绝对路径,如果上级目录不存在则自动创建
<append> 如果为 true 表示日志被追加到文件结尾,如果为 false 表示清空现有文件,默认是 true
<encoder> 同上
<prudent> 如果为 true 表示日志会被安全地写入文件,即使其他的 FileAppender 也在向此文件做写入操作,效率低,默认为 false
4.3 RollingFileAppender

RollingFileAppender 的作用是滚动记录文件,先将日志记录到指定文件,当符合某个条件时再将日志记录到其他文件

1
2
3
4
5
6
7
8
9
<appender name="DEMO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.root}/demo.log</file>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${log.root}/demo.%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>

常用子节点 描述
<file> 同上
<append> 同上
<rollingPolicy> 当发生滚动时决定 RollingFileAppender 的行为,涉及到文件移动和重命名
<encoder> 同上

上述 <rollingPolicy> 属性 class 定义具体的滚动策略类,「 TimeBasedRollingPolicy 」是最常用的滚动策略,它根据时间制定滚动策略,既负责滚动也负责触发滚动。有以下子节点:

常用子节点 描述
<fileNamePattern> 必要节点,包含文件名及「 %d 」转换符,「 %d 」可以包含一个 java.text.SimpleDateFormat 类指定的时间格式,如 %d{yyyy-MM},如果直接使用则默认格式为 yyyy-MM-dd
<maxHistory> 可选节点,控制保留的归档文件的最大数量,超出数量则删除旧文件

RollingFileAppender 的 <file> 子节点可有可无,如果没设置则会根据 <fileNamePattern> 的值每隔一段时间改变一次。

5. <logger>

子节点 <logger> 是用来设置某一个包或具体某一个类的日志级别以及指定要使用的 appender。它有三个属性,一个必选的 name 属性,一个可选的 level 属性和一个可选的 addtivity 属性。可以包含零个或多个 <appender-ref> 元素,标识该 appender 将会添加到这个 logger。

  • name :用来指定受此 logger 约束的某一个包或者具体的一个类
  • level :用来设置日志级别,大小写无关。五个常用的日志级别从低至高依次为 TRACE 、 DEBUG 、 INFO 、 WARN 、 ERROR ,如果未设置此属性,那么当前 logger 将会继承上级的日志级别
  • addtivity :是否向上级 logger 传递打印信息,默认为 true

6. <root>

子节点 <root> 也是 <logger> 元素,但它是根 logger,是所有 logger 的上级。只有一个 level 属性,因为 name 已经被命名为「 root 」了。默认日志级别为 DEBUG。

7. <filter>

<filter> 是 <appender> 的一个子节点,表示在当前设置的日志级别下再进行一次过滤,最基本的 filter 为 LevelFilter 和 ThresholdFilter。

7.1 LevelFilter

LevelFilter 即级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据 onMath 和 onMismatch 的值接收或拒绝日志。有以下子节点:

  • <level> :设置日志级别
  • <onMatch> :用于配置符合过滤条件的操作
  • <onMismatch> :用于配置不符合过滤条件的操作

例:将过滤器的日志级别配置为 INFO,所有 INFO 级别的日志交给 appender 处理,非 INFO 级别的日志被过滤掉。

① 首先定义一个 ConsoleAppender 类型的 appender,再在其中声明一个 class 为 LevelFilter 的 filter。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<configuration scan="true" scanPeriod="60 seconds" debug="false" >

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{'MM-dd HH:mm:ss,SSS',GMT+8:00}] %level [%thread] %logger{0} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>

</configuration>

② 新建日志输出单元测试类

1
2
3
4
5
6
7
8
9
10
11
public class LogbackTest {

@Test
public void testLog() {
log.trace("=====trace=====");
log.debug("=====debug=====");
log.info("=====info=====");
log.warn("=====warn=====");
log.error("=====error=====");
}
}

③ 输出结果为:

1
[01-29 10:44:00,254] INFO [main] LogbackTest - =====info=====

可以看到,尽管 <root> 配置的日志级别为 DEBUG,但是输出的只有 INFO 。

7.2 ThresholdFilter

ThresholdFilter 即临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。

例:过滤掉所有低于INFO级别的日志。

① 首先定义一个 ConsoleAppender 类型的 appender,再在其中声明一个 class 为 ThresholdFilter 的 filter。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<configuration scan="true" scanPeriod="60 seconds" debug="false" >

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{'MM-dd HH:mm:ss,SSS',GMT+8:00}] %level [%thread] %logger{0} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
</appender>

<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>

</configuration>

② 运行 Logback 单元测试类的 testLog 方法,输出结果为:

1
2
3
[01-29 10:46:39,937] INFO [main] LogbackTest - =====info=====
[01-29 10:46:39,937] WARN [main] LogbackTest - =====warn=====
[01-29 10:46:39,937] ERROR [main] LogbackTest - =====error=====

可以看到,尽管 <root> 配置的日志级别为 DEBUG,但是输出的只有 INFO 及以上级别的。