日志管理
项目采用 SLF4J + Logback 日志框架,支持多环境配置、日志滚动、级别过滤等特性。
日志框架
技术选型
| 框架 | 说明 |
|---|---|
| SLF4J | 日志门面,提供统一的日志接口 |
| Logback | 日志实现,Spring Boot 默认集成 |
依赖配置(Spring Boot 自动引入):
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 内部包含 spring-boot-starter-logging -->
</dependency>日志级别
日志级别从低到高:
TRACE < DEBUG < INFO < WARN < ERROR < FATAL| 级别 | 说明 | 适用场景 |
|---|---|---|
| TRACE | 追踪信息 | 调试时详细跟踪 |
| DEBUG | 调试信息 | 开发环境调试 |
| INFO | 普通信息 | 关键业务节点 |
| WARN | 警告信息 | 潜在问题提示 |
| ERROR | 错误信息 | 异常情况记录 |
级别规则:设置某级别后,只输出大于等于该级别的日志。
配置文件
配置文件位置
src/main/resources/logback-spring.xml完整配置
xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 引入 Spring Boot 默认配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!-- 应用名称(从 application.yml 读取) -->
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
<!-- 日志存储路径 -->
<property name="LOG_HOME" value="/logs/${APP_NAME}"/>
<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 文件输出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/log.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} -%5level ---[%15.15thread] %-40.40logger{39} : %msg%n%n</pattern>
<charset>UTF-8</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>10MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<!-- 开发环境:仅控制台输出 -->
<springProfile name="dev">
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<!-- 生产环境:控制台 + 文件输出 -->
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</springProfile>
</configuration>配置详解
日志路径
xml
<property name="LOG_HOME" value="/logs/${APP_NAME}"/>实际路径:/logs/youlai-boot/log.log
Docker 挂载:
yaml
# docker-compose.yml
services:
youlai-boot:
volumes:
- /logs/youlai-boot:/logs/youlai-boot日志格式
xml
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} -%5level ---[%15.15thread] %-40.40logger{39} : %msg%n%n</pattern>输出示例:
2024-01-15 10:30:45.123 - INFO ---[nio-8000-exec-1] c.y.b.a.controller.AuthController : 用户登录成功: admin格式说明:
| 占位符 | 说明 | 示例 |
|---|---|---|
%d | 时间戳 | 2024-01-15 10:30:45.123 |
%5level | 日志级别(5字符宽度) | INFO |
%thread | 线程名 | nio-8000-exec-1 |
%logger{39} | Logger名称(最长39字符) | c.y.b.a.controller.AuthController |
%msg | 日志消息 | 用户登录成功 |
%n | 换行符 | - |
滚动策略
xml
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>10MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>配置说明:
| 配置项 | 值 | 说明 |
|---|---|---|
fileNamePattern | %d{yyyy-MM-dd}.%i.log | 按日期+序号命名 |
maxFileSize | 10MB | 单文件最大 10MB |
maxHistory | 30 | 保留 30 天 |
totalSizeCap | 1GB | 总大小不超过 1GB |
滚动示例:
/logs/youlai-boot/
├── log.log # 当前日志文件
├── 2024-01-15.0.log # 当天第1个归档
├── 2024-01-15.1.log # 当天第2个归档
├── 2024-01-14.0.log # 昨天第1个归档
└── ...日志级别过滤
xml
<!-- 控制台:DEBUG及以上 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<!-- 文件:INFO及以上 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>效果:控制台输出 DEBUG 及以上,文件只记录 INFO 及以上。
多环境配置
开发环境(dev)
xml
<springProfile name="dev">
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>特点:
- 仅输出到控制台
- 便于开发调试
- 无文件存储
生产环境(prod)
xml
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</springProfile>特点:
- 控制台 + 文件双输出
- 支持日志滚动归档
- 便于问题排查
日志使用
基本用法
java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Service
@Slf4j // Lombok 注解,自动生成 log 对象
public class UserService {
// 方式一:Lombok 注解(推荐)
public void createUser(UserForm form) {
log.info("创建用户: {}", form.getUsername());
log.debug("用户详情: {}", form);
log.error("创建用户失败: {}", form.getUsername(), e);
}
// 方式二:手动创建 Logger
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
public void updateUser(UserForm form) {
logger.info("更新用户: {}", form.getUsername());
}
}日志级别使用规范
| 级别 | 使用场景 | 示例 |
|---|---|---|
| DEBUG | 调试信息、详细参数 | log.debug("查询参数: {}", params) |
| INFO | 关键业务节点 | log.info("用户登录成功: {}", username) |
| WARN | 潜在问题、降级处理 | log.warn("缓存失效,回源数据库") |
| ERROR | 异常情况、错误记录 | log.error("订单创建失败: {}", orderId, e) |
参数化日志
java
// ✅ 推荐:参数化方式
log.info("用户 {} 登录成功,IP: {}", username, ip);
// ❌ 不推荐:字符串拼接
log.info("用户 " + username + " 登录成功,IP: " + ip);异常日志
java
try {
// 业务逻辑
orderService.createOrder(order);
} catch (Exception e) {
// 最后一个参数是异常对象,会打印完整堆栈
log.error("订单创建失败: orderId={}", order.getId(), e);
}输出效果:
2024-01-15 10:30:45.123 -ERROR ---[nio-8000-exec-1] c.y.b.o.service.OrderService : 订单创建失败: orderId=12345
java.lang.NullPointerException: 商品不存在
at com.youlai.boot.order.service.OrderService.createOrder(OrderService.java:50)
...Docker 日志管理
目录挂载
yaml
# docker-compose.yml
services:
youlai-boot:
image: youlai-boot:latest
volumes:
- /logs/youlai-boot:/logs/youlai-boot # 日志目录挂载
environment:
- SPRING_PROFILES_ACTIVE=prod日志查看
bash
# 查看当前日志
tail -f /logs/youlai-boot/log.log
# 查看指定日期日志
cat /logs/youlai-boot/2024-01-15.0.log
# 搜索关键字
grep "ERROR" /logs/youlai-boot/log.log
# 实时监控错误日志
tail -f /logs/youlai-boot/log.log | grep "ERROR"Docker 容器日志
bash
# 查看容器标准输出
docker logs youlai-boot
# 实时跟踪
docker logs -f youlai-boot
# 查看最近 100 行
docker logs --tail 100 youlai-boot日志最佳实践
敏感信息脱敏
java
// ❌ 不推荐:记录敏感信息
log.info("用户登录: password={}", password);
// ✅ 推荐:脱敏处理
log.info("用户登录: phone={}", maskPhone(phone));
private String maskPhone(String phone) {
if (phone == null || phone.length() < 7) {
return phone;
}
return phone.substring(0, 3) + "****" + phone.substring(phone.length() - 4);
}日志级别配置
yaml
# application.yml
logging:
level:
root: INFO # 全局级别
com.youlai.boot: DEBUG # 项目包级别
org.springframework.web: INFO # 框架日志级别
org.springframework.security: WARN # 安全框架日志性能优化
java
// ✅ 推荐:使用条件判断(DEBUG 级别未开启时不执行拼接)
if (log.isDebugEnabled()) {
log.debug("复杂对象序列化: {}", objectMapper.writeValueAsString(obj));
}
// ❌ 不推荐:始终执行序列化
log.debug("复杂对象序列化: {}", objectMapper.writeValueAsString(obj));MDC 链路追踪
java
import org.slf4j.MDC;
@Component
public class TraceFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// 生成链路ID
String traceId = UUID.randomUUID().toString().replace("-", "");
MDC.put("traceId", traceId);
try {
chain.doFilter(request, response);
} finally {
MDC.clear();
}
}
}日志格式添加 traceId:
xml
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] -%5level ---[%thread] %logger{39} : %msg%n</pattern>输出效果:
2024-01-15 10:30:45.123 [a1b2c3d4e5f6] - INFO ---[nio-8000-exec-1] c.y.b.a.controller.AuthController : 用户登录成功日志文件管理
磁盘空间监控
bash
# 查看日志目录大小
du -sh /logs/youlai-boot
# 查看各文件大小
du -h /logs/youlai-boot
# 清理 7 天前的日志(谨慎操作)
find /logs/youlai-boot -name "*.log" -mtime +7 -delete日志轮转策略
| 参数 | 开发环境 | 生产环境 |
|---|---|---|
maxFileSize | 10MB | 50MB |
maxHistory | 7 天 | 30 天 |
totalSizeCap | 500MB | 5GB |
相关文件
| 文件 | 说明 |
|---|---|
logback-spring.xml | Logback 配置文件 |
application-dev.yml | 开发环境配置 |
application-prod.yml | 生产环境配置 |
Dockerfile | Docker 构建配置 |
