Logback 使用入门

Logback is intended as a successor to the popular log4j project, picking up where log4j leaves off.

Logback 是什么

Logback 是一个基于 Java 的日志记录工具。它是由 Log4j 的作者设计开发的又一个开源日志组件。意图将 Logback 打造为 Log4j 的继任者。

目前 Logback 分为三个模块:logback-core,logback-classic 和 logback-access。

  • logback-core 模块是其基础包
  • logback-classic 模块是吸收了 Log4j 诸多优点的改进版本。在该模块中,实现了 SLF4J API 可以方便的更换成其他日志管理工具。
  • logback-access 模块可与 Servlet 容器(如 Tomcat、Jetty)集成,以提供 HTTP 访问日志的功能

SLF4J (Simple Logging Facade for Java) 与其他日志类库不同。SLF4J 不是真正的日志实现,而是抽象层,它允许你在后台使用任意一个实现了 SLF4J API 的日志类库。底层的日志记录是在运行时通过向类路径添加所需的绑定来确定的,可能是 Java Logging API(java.util.logging), Log4j, Logback 或 tinylog。

引入 Logback

使用 Logback,至少需引入 logback-core、logback-classic 依赖包。

但是通常来说,我们还会使用 slf4j-api 用于简化我们的使用或对未来的拓展。

如使用 Maven,则可以在 pom.xml 文件中,通过添加以下 XML 引入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-access -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.2.3</version>
</dependency>

也可以只引入 logback-classic 模块。Maven 会自动引入 logback-core 和 slf4j-api 依赖包。

使用 Logback

创建 Java 项目,引入依赖包。

新建类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package xyz.yamdestiny.demo.logback;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class App {

private static final Logger logger = LoggerFactory.getLogger(App.class);

public static void main(String[] args) {
logger.trace("Hello World!");
logger.debug("Hello World!");
logger.info("Hello World!");
logger.warn("Hello World!");
logger.error("Hello World!");
}

}

运行即可在控制台看到如下输出结果。

1
2
3
4
20:16:36.098 [main] DEBUG xyz.yamdestiny.demo.logback.App - Hello World!
20:16:36.101 [main] INFO xyz.yamdestiny.demo.logback.App - Hello World!
20:16:36.101 [main] WARN xyz.yamdestiny.demo.logback.App - Hello World!
20:16:36.101 [main] ERROR xyz.yamdestiny.demo.logback.App - Hello World!

这是 Logback 的默认配置。如果配置文件 logback-test.xmllogback.xml 都不存在,那么 Logback 默认地会调用 BasicConfigurator,创建基础配置。基础配置由 root 关联一个 ConsoleAppender 组成。输出用 Pattern%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%nPatternLayoutEncoder 进行格式化。root 的默认级别是 DEBUG

输出级别说明:
TRACE < DEBUG < INFO < WARN < ERROR < OFF
当设置级别为 OFF 时,什么都不输出
当设置级别为 ERROR 时,只会输出 ERROR 级的消息
当设置级别为 WARN 时,会输出 WARN 和 ERROR 级的消息
INFO,DEBUG,TRACE 同理。
当设置级别为 TRACE 时,会输出所有级别的消息

配置 Logback

虽然 Logback 有默认配置,但是要在项目中使用还是需要进行一些针对性的配置。

Logback 可以使用 编程的方式、XML 或 Groovy 格式表示的配置脚本来配置 Logback。

Logback 配置初始化策略:

  1. Logback 会尝试在 classpath 中查找名为 logback-test.xml 的配置文件
  2. 如果未找到该文件,则 Logback 会尝试在 classpath 中查找名为 logback.groovy 的配置文件
  3. 如果未找到这些文件,则 Logback 会尝试在 classpath 中查找名为 logback.xml 的配置文件
  4. 如果没有找到以上所列的配置文件,则 Logback 会使用在 JDK 1.6 中引入的 服务提供者加载工具(service-provider loading facility)通过在 classpath 中查找 META-INF\services 下实现了 com.qos.logback.classic.spi.Configurator 接口的Configurator类。

如果以上配置初始化都不成功,那么 Logback 将使用 BasicConfigurator 进行初始化配置,就像 如何使用 Logback 章节中的一样。

配置文件

以 XML 格式 作为示例。

classpath 内的任意位置新建 logback.xml 文件。通常如 src/main/resources/configWEB-INF/config

示例内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<configuration>
<!-- ConsoleAppender用于输出到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 输出内容的格式 -->
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<!-- 根,有且仅有一个 -->
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>

对于以上 XML 文件的内容,可作如下解释:

  1. 对于整个日志的记录,有且仅有一条主线或大树的根部,即为 root 标签,输出级别为 debug
  2. 对于 root 中的 <appender-ref ref="STDOUT" /> 标签,表示要使用名为 STDOUT 的一个 appender。
  3. STDOUT appender 的 class 是 ch.qos.logback.core.ConsoleAppender,该类表示往控制台追加输出内容
  4. 输出内容的格式即为 pattern 标签中的内容,即
    1
    2
    %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}    - %msg    %n
    时间 线程名 日志级别 输出日志的Logger - 输出消息 换行

输出到文件

FileAppender

1
2
3
4
5
6
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>file.log</file>
<encoder>
<pattern>%d %-5level [%thread] %logger{36} - %m%n</pattern>
</encoder>
</appender>

RollingFileAppender

1
2
3
4
5
6
7
8
9
10
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>rolling.log</file>
<encoder>
<pattern>%d %-5level [%thread] %logger{36} - %m%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>rolling.%d{yyyy-MM-dd_HH}.log</fileNamePattern>
<maxHistory>720</maxHistory>
</rollingPolicy>
</appender>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>file.log</file>
<encoder>
<pattern>%d %-5level [%thread] %logger{36} - %m%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/world.%d{yyyy-MM-dd_HH}.log</fileNamePattern>
<maxHistory>720</maxHistory>
</rollingPolicy>
</appender>

<root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="ROLLING" />
</root>
</configuration>

设置子节点

子节点用于分层精细控制信息的输出。使用 logger 标签进行设置。

示例

1
2
3
4
5
6
7
8
<!-- name 是必须的属性,表示控制范围 -->
<!-- leval 控制输出级别 -->
<!-- additivity 控制父子的Appender打印关系,true继承,false不继承 -->
<!-- additivity="true" 该 name 的所有 log 将输出到 ROOT 和 LOGGER 的 Appender 中,默认为 "true" -->
<!-- additivity="false" 该 name 的所有 log 将只输出到 LOGGER -->
<logger name="xyz.yamdestiny.demo" level="WARN" additivity="true">
<appender-ref ref="hello" />
</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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<!-- scan 表示修改配置文件后自动重新加载,默认是true -->
<!-- scanPeriod 表示扫描配置文件变更的间隔时间,默认是1分钟,单位可以是 milliseconds, seconds, minutes or hours -->
<!-- debug 表示是否打印出 Logback 内部日志信息,用于查看运行状态,默认是false -->
<configuration scan="true" scanPeriod="30 seconds" debug="false">
<contextName>WEB</contextName>

<!-- 日志文件存放路径 -->
<property name="LOG_PATH" value="logs" />
<!-- 控制台输出模式 -->
<property name="CONSOLE_PATTERN" value="%d{HH:mm:ss.SSS} %-5level [%contextName] %logger{36}\\(%file:%line\\) - %msg%n" />
<!-- 文件输出模式 -->
<property name="FILE_PATTERN" value="%date %-5level [%contextName] [%thread] %logger{36} - %msg%n" />
<!-- 文件后缀, e.g .2018-09-01_13 -->
<property name="FILE_SUFFIX_HH" value=".%d{yyyy-MM-dd_HH}" />
<!-- 文件后缀, e.g .2018-09-01 -->
<property name="FILE_SUFFIX_DD" value=".%d{yyyy-MM-dd}" />
<!-- 最多720个日志文件,如FILE_SUFFIX_HH,每小时更新日志文件,720/24h = 30d, 即30天的日志 -->
<property name="CONSOLE_MAX_HISTORY" value="720" />
<!-- 最多30个日志文件,如FILE_SUFFIX_DD,每天更新日志文件,即30天的日志 -->
<property name="MODULE_MAX_HISTORY" value="30" />

<!-- 控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_PATTERN}</pattern>
</encoder>
</appender>

<!-- 文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 e.g logs/server.log -->
<file>${LOG_PATH}/server.log</file>
<encoder>
<pattern>${FILE_PATTERN}</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档文件路径 e.g logs/server/server.2018-09-01_13.0.log.zip -->
<!-- 此处的 %i 用于超过最大文件大小后,生成归档文件的自增序列 -->
<!-- 如不使用 TimeBasedFileNamingAndTriggeringPolicy ,不需要填写,否则在解析文件名时,会被当作时间的一部分解析,导致不能正常生成归档文件 -->
<fileNamePattern>${LOG_PATH}/server/server${FILE_SUFFIX_HH}.%i.log.zip</fileNamePattern>
<!-- 最多归档日志文件数量 -->
<maxHistory>${CONSOLE_MAX_HISTORY}</maxHistory>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 单个日志文件最大大小,超过则生成归档文件(%i) -->
<MaxFileSize>100MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>

<appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 e.g logs/error.log -->
<file>${LOG_PATH}/error.log</file>
<!-- 过滤日志等级,表示只输出 ERROR 级别以上的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>${FILE_PATTERN}</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 归档文件路径 e.g logs/error/error.2018-09-01.log.zip -->
<fileNamePattern>${LOG_PATH}/error/error${FILE_SUFFIX_DD}.log.zip</fileNamePattern>
<maxHistory>${MODULE_MAX_HISTORY}</maxHistory>
</rollingPolicy>
</appender>

<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
<appender-ref ref="ERROR" />
</root>
</configuration>

参考文献