Skip to content

日志管理

当你需要排查线上问题、定位请求链路、或建立日志平台时,这份文档给出日志体系的落地做法。

你将了解:

  • 日志分层与输出策略(业务/审计/操作/异常)
  • 日志滚动与保留策略
  • 生产环境对接 ELK 的典型链路

日志框架

技术选型

框架说明
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按日期+序号命名
maxFileSize10MB单文件最大 10MB
maxHistory30保留 30 天
totalSizeCap1GB总大小不超过 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

架构设计

整体架构

youlai-boot 采用 SLF4J + Logback 作为核心日志框架,生产环境可扩展集成 ELK (Elasticsearch + Logstash + Kibana) 技术栈构建企业级日志平台:

设计原则

原则实现方式
异步不阻塞Logback AsyncAppender,减少日志 I/O 对业务线程的影响
结构化存储JSON 格式输出(可选),ES 直接索引无需解析
可观测性MDC TraceId 全链路追踪,请求完整生命周期可追溯
安全性敏感字段自动脱敏,避免密码、Token 泄露到日志

日志分层规范

层级Logger 用途输出目标示例
业务日志关键业务节点文件 + 控制台用户登录、订单创建
审计日志数据变更记录数据库 + 文件权限修改、配置更新
操作日志管理员行为数据库who + when + what
异常日志错误和堆栈文件接口超时、SQL 异常

MDC 链路追踪

每个请求在进入系统时生成唯一 TraceId,贯穿整个调用链:

Request → Filter [生成 TraceId]
         → Controller [TraceId: a1b2c3]
           → Service [TraceId: a1b2c3]
             → Mapper [TraceId: a1b2c3]
         → Response

日志输出中携带 traceId,便于在 Kibana 中聚合查看一次请求的完整日志链路:

json
{
  "traceId": "a1b2c3d4e5f6",
  "service": "system-service",
  "userId": 1,
  "method": "UserController.getPage",
  "duration": 156,
  "status": "SUCCESS"
}

MDC 配置方式见上方「MDC 链路追踪」小节。

生产环境 ELK 集成参考

组件版本用途配置位置
Elasticsearch8.x日志存储与全文检索9200 端口
Kibana8.x可视化分析面板5601 端口
Logstash8.x日志处理管道(解析/过滤)pipeline/log.conf
Filebeat8.x轻量级日志采集器filebeat.yml

开发环境不需要部署完整的 ELK 栈,本地调试直接查看日志文件即可。生产环境建议使用 Docker Compose 一键部署。


日志最佳实践

敏感信息脱敏

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

日志轮转策略

参数开发环境生产环境
maxFileSize10MB50MB
maxHistory7 天30 天
totalSizeCap500MB5GB

相关文件

文件说明
logback-spring.xmlLogback 配置文件
application-dev.yml开发环境配置
application-prod.yml生产环境配置
DockerfileDocker 构建配置

下一步

参考资料

基于 MIT 许可发布 · 由 ❤️ 和 ☕ 驱动 · 支持作者