Logback 使用总结

最近打在打印日志这块栽了个跟头,发现日志这块掌握得还不太好,所以大概梳理一下。

其实 SLF4J 类似于 Commons Logging,也是一个日志接口,而 Logback 类似于 Log4j,是一个日志的实现。

4 个日志级别

常用的 4 个日志级别,从低到高:DEBUG、INFO、WARN、ERROR。低级别能输出高级别的日志,级别越低输出内容越多。

  • DEBUG:调试数据,生产环境关闭 Debug
  • INFO:系统运行信息、外部接口部分,可通过日志看到功能流程
  • WARN:不影响程序正常运行,但不应该出现的情况
  • ERROR:影响程序正常运行的情况,此时需使用邮件等方式告警,如果抛出异常,不打印

使用 Logger 或使用注解 @Slf4j

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

class Main {
final Logger logger = LoggerFactory.getLogger(getClass());
@GetMapping("/test")
@ResponseBody
public String test() {
logger.debug("debug: [{}]", "haha");
logger.info("info: [{}]", "haha");
logger.warn("warn: [{}]", "haha");
logger.error("error: [{}]", "haha");
return "test";
}
}
import lombok.extern.slf4j.Slf4j;
@Slf4j
class Main {
@GetMapping("/test")
@ResponseBody
public String test() {
log.debug("debug: [{}]", "haha");
log.info("info: [{}]", "haha");
log.warn("warn: [{}]", "haha");
log.error("error: [{}]", "haha");
return "test";
}
}

打印日志时,使用占位符和 [],当没有 logback.xml 时,默认隔离级别:INFO。

Logback 配置

logback.xml 基础配置:

<configuration>

<!--控制台输出设置-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

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

输出格式:

15:58:50.559 [http-nio-8080-exec-1] INFO  w.depp.exceptionlog.TestController - info: haha

basic Syntax

使用 logger 指定某个 package 使用某个级别:

<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<logger name="chapters.configuration" level="INFO"/>

<!-- Strictly speaking, the level attribute is not necessary since -->
<!-- the level of the root level is set to DEBUG by default. -->
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>

</configuration>

使用 logger 指定某个文件使用某个级别:

<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>

<logger name="chapters.configuration" level="INFO" />
<logger name="chapters.configuration.Foo" level="DEBUG" />

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

</configuration>

为不同的环境配置不同的日志级别

有时候我们在系统整体使用某个级别外(如 INFO),还可以业务类针对不同的环境配置不同的日志级别,使用 springProfile 标签

<configuration debug="true">
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

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

<springProfile name="test,dev">
<logger name="wang.depp" level="DEBUG">
<appender-ref ref="STDOUT" />
</logger>
</springProfile>

<springProfile name="pre,pro">
<logger name="wang.depp" level="INFO">
<appender-ref ref="STDOUT" />
</logger>
</springProfile>
</configuration>

本地 application.yml 配置环境参数

spring:
profiles:
active: dev

打包部署时指定环境

$ java -jar \target\my-app.jar -Dspring.profiles.active=dev

默认 appender 将重复打印日志,此时可以通过在 logger 添加 additivity="false" 来关闭

<springProfile name="pre,pro">
<logger name="wang.depp" level="INFO" additivity="false">
<appender-ref ref="STDOUT" />
</logger>
</springProfile>

输出到日志文件

<configuration debug="true">

<include resource="org/springframework/boot/logging/logback/base.xml"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<appender name="baselog"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>log/app.log</File>
<!--根据日期存放日志,每个文件限制 64MB -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>log/app.log.%d.%i</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--or whenever the file size reaches 64 MB-->
<maxFileSize>64 MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!--日志文件的日志格式-->
<encoder>
<pattern>
%d %p (%file:%line\)- %m%n
</pattern>
<charset>UTF-8</charset>
<!-- 此处设置字符集 -->
</encoder>
</appender>

<springProfile name="test,dev">
<logger name="wang.depp" level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="baselog"/>
</logger>
</springProfile>

<springProfile name="pre,pro">
<logger name="wang.depp" level="error">
<appender-ref ref="STDOUT" />
<appender-ref ref="baselog"/>
</logger>
</springProfile>
</configuration>

搭建 ELK 平台图形化查看日志

ELK:Elasticsearch、Logstash、Kibana

大致原理:

图 1. ELK 的大致工作流程

详细搭建过程:搭建 ELK 实时日志平台并在 Spring Boot 和 Nginx 项目中使用

延伸阅读

Depp Wang wechat
个人公众号