一、Java 日志框架简介
Java 日志框架主要分为两类:日志门面和具体的日志实现。
1. 日志门面
日志门面提供了统一的日志接口,使得开发者可以灵活地更换底层的日志框架而无需修改代码。常见的日志门面有:
- Jakarta Commons Logging (JCL):只支持 JUL 和 Log4j。
- Simple Logging Facade for Java (SLF4J):支持几乎所有主流的日志框架。
2. 日志实现
日志实现框架提供了具体的日志记录功能。常见的实现有:
- Java Util Logging (JUL):JDK 自带的日志实现。
- Log4j:由 Apache 软件基金会提供,是最早的日志框架之一。
- Logback:由 Log4j 的创始人设计,性能优化,支持 SLF4J。
- Log4j2:Log4j 的升级版,重新架构,性能和特性上有显著提升。
3.日志级别
使用日志级别的好处在于,调整级别,就可以屏蔽掉很多调试相关的日志输出。不同的日志实现定义的日志级别不太一样,不过也都大同小异。
- Java Util Logging
Java Util Logging 定义了 7 个日志级别,从严重到普通依次是:
-
SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST
-
因为默认级别是 INFO,因此 INFO 级别以下的日志,不会被打印出来。
- Log4j
Log4j 定义了 8 个日志级别(除去 OFF 和 ALL,可以说分为 6 个级别),从严重到普通依次是:
- OFF:最高等级的,用于关闭所有日志记录。
- FATAL:重大错误,这种级别可以直接停止程序了。
- ERROR:打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。
- WARN:警告提示。
- INFO:用于生产环境中输出程序运行的一些重要信息,不能滥用。
- DEBUG:用于开发过程中打印一些运行信息。
TRACE - ALL 最低等级的,用于打开所有日志记录。
- Logback
Logback 日志级别比较简单,从严重到普通依次是:
- ERROR、 WARN、INFO、DEBUG、TRACE
二、 Spring Boot默认日志框架
Spring Boot默认使用的日志框架是SLF4J+Logback。这个组合是当下的最优选择,原因如下:
- SLF4J是日志接口规范,可以通过配置不同的桥接器,来为项目接入不同的日志框架。更改日志框架无需改动代码。
- Logback是由log4j创始人设计的又一个开源日志组件,在性能和架构上较log4j有着很大程度上的改进,并且logback是Spring Boot框架(1.x和2.x)默认集成的日志实现框架。
- Log4j2是对log4j的升级,提供了重要的改进,并提供了Logback中可用的许多改进,同时修复了Logback体系结构中的一些固有问题。可以认为log4j2是logback的加强版。
打开一个SpringBoot应用的pom.xml 文件,可看到其中导入 了spring-boot-starter-web 依赖;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
spring-boot-starter-web 依赖中包含 spring-boot-stater 依赖;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.7.15</version>
<scope>compile</scope>
</dependency>
spring-boot-stater 依赖中包含 spring-boot-starter-logging 依赖用于配置日志相关;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<version>2.7.15</version>
<scope>compile</scope>
</dependency>
查看 spring-boot-starter-logging 的 pom 发现依赖于如下:
其中:
- logback-classic:
这是一个具体的日志框架,即 Logback 的经典版本。Logback 是 SLF4J(Simple Logging Facade for Java)的一个实现,它提供了高效的日志记录功能。 - log4j-to-slf4j:
这个依赖用于将 Log4j 的日志调用重定向到 SLF4J。 - jul-to-slf4j:
这个依赖用于将 Java 自带的日志系统(java.util.logging,简称 JUL)的日志调用重定向到 SLF4J。
三、 Spring Boot默认日志框架 Logback 集成
1.引入 spring-boot-starter-logging
pom 文件添加:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
spring-boot-starter 中已经引入了 spring-boot-starter-logging ,我们可以直接在项目中使用 spring-boot-starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
2. Logback配置文件加载顺序
在logback框架读取日志配置文件的优先级从高到低依次是:
日志加载顺序:logback.xml > application.properties > logback-spring.xml
配置文件的最佳选择
-
logback.xml:来配置日志框架,该配置文件可直接就被日志框架识别了;一般情况不推荐。
-
logback-spring.xml:日志框架不直接加载日志的配置项,由SpringBoot解析日志配置,Spring Boot 官方推荐优先使用带有 -spring 的文件名作为你的日志配置。命名为 logback-spring.xml 的日志配置文件,可以为它添加一些 spring boot 特有的配置项。
3. logback-spring.xml 配置实例
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--定义日志文件的存储地址,使用Spring的属性文件配置方式-->
<springProperty scope="context" name="log.home" source="log.home" defaultValue="logs"/>
<!--定义日志文件的路径-->
<property name="LOG_PATH" value="${log.home}"/>
<!--定义控制台输出-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<!--定义 INFO 及以上级别信息输出到控制台-->
<root level="INFO">
<appender-ref ref="console"/>
</root>
<!--定义所有组件的日志级别,如所有 DEBUG-->
<logger name="com.example" level="DEBUG"/>
<!-- date 格式定义 -->
<property name="LOG_DATEFORMAT" value="yyyy-MM-dd"/>
<!-- 定义日志归档文件名称格式,每天生成一个日志文件 -->
<property name="ARCHIVE_PATTERN" value="${LOG_PATH}/%d{${LOG_DATEFORMAT}}/app-%d{${LOG_DATEFORMAT}}-%i.log.gz"/>
<!--定义文件输出,会根据定义的阈值进行切割,支持自动归档压缩过期日志-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--定义日志文件切割的阈值,本例是 50MB-->
<maxFileSize>50MB</maxFileSize>
<!--定义日志文件保留时间,本例是每天生成一个日志文件-->
<fileNamePattern>${ARCHIVE_PATTERN}</fileNamePattern>
<maxHistory>30</maxHistory>
<!-- zip 压缩生成的归档文件 -->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>50MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 删除过期文件 -->
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<!--定义 ERROR 级别以上信息输出到文件-->
<logger name="com.example.demo" level="ERROR" additivity="false">
<appender-ref ref="file"/>
</logger>
<!--异步输出日志信息-->
<appender name="asyncFile" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>256</queueSize>
<appender-ref ref="file"/>
</appender>
<!--定义INFO及以上级别信息异步输出到文件-->
<logger name="com.example" level="INFO" additivity="false">
<appender-ref ref="asyncFile"/>
</logger>
</configuration>
4. application.yml 配置文件实现日志配置
############## logback 日志自定义配置 ##############
logging:
level:
root: info
com.dz.demo.controller: debug
file:
path: D:\logs
name: D:\logs\boot-launch.log
max-size: 10MB
max-history: 180
pattern:
console: '%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{10}) - %cyan(%msg%n)'
file: '%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger : %msg%n'
- logging.level.root=info #指定整个系统的默认日志级别是info,日志级别统一化
- logging.level.com.dz.demo.controller=debug #指定某个特定的package的日志级别是debug,日志级别个性化。优先级角度,个性配置大于统一配置。
- logging.file.path #将日志输出到指定目录,如果不指定logging.file.name,日志文件的默认名称是spring.log。配置了 logging.file.name之后,logging.file.path配置失效。
- 无论何种设置,Spring Boot都会自动按天分割日志文件,也就是说每天都会自动生成一个新的log文件,而之前的会自动打成GZ压缩包。# 日志文件大小
- logging.file.max-size=10MB #分割的每个日志的文件最大容量,超过这个size之后日志继续分隔。
- logging.file.max-history=180 #设置保留的日志时间以天为单位
- logging.pattern.file #输出到文件中的日志的格式
- logging.pattern.console #控制台输出日志的格式,控制台调试时候显示效果更清晰,为日志增加了颜色。red、green等等
日志格式占位符
配合这张图,看一下占位符和logging.pattern.console格式配置之间的关系
- %d{HH:mm:ss.SSS}:日志输出时间(red)
- %thread:输出日志的进程名字,这在Web应用以及异步任务处理中很有用 (green)
- %-5level:日志级别,并且使用5个字符靠左对齐 (highlight高亮蓝色)
- %logger:日志输出类的名字 (boldMagenta粗体洋红色)
- %msg:日志消息 (cyan蓝绿色)
- %n:平台的换行符
四、日志使用
- 在使用 SLF4J 进行日志记录时,通常都需要在每个需要记录日志的类中定义 Logger 变量,如下所示:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@RestController
public class LogController {
private static final Logger logger = LoggerFactory.getLogger(LogController.class);
@GetMapping("/test")
public void test(){
logger.trace("Trace 日志...");
logger.debug("Debug 日志...");
logger.info("Info 日志...");
logger.warn("Warn 日志...");
logger.error("Error 日志...");
}
}
- 当我们在项目中引入了 Lombok,可以使用它提供的 @Slf4j 注解来自动生成上面那个变量,默认的变量名是 log
@Slf4j
@RestController
public class LogController {
@GetMapping("/test")
public void test(){
log.trace("Trace 日志...");
log.debug("Debug 日志...");
log.info("Info 日志...");
log.warn("Warn 日志...");
log.error("Error 日志...");
}
}
如果我们想采用 LOGGER 变量名,可以增加 lombok.config 文件,
并在文件中增加 lombok.log.fieldName=LOGGER 的配置项即可
参考文档:
https://cloud.tencent.com/developer/article/1914231
https://cloud.tencent.com/developer/article/2354562