在 Spring Boot 与 Spring Cloud 应用开发中,规范化的日志书写对系统可观测性、问题排查、运维监控至关重要。虽然 Java 本身没有强制的日志格式标准,但业界(尤其在金融、保险等强监管行业)普遍形成了一套推荐实践和指导性规范。以下是一份面向实际 Java 后端开发(尤其是 Spring Boot/Spring Cloud)的日志指南,涵盖格式、内容、级别、安全、性能等维度。
一、日志框架选型(基础)
Spring Boot 默认使用 SLF4J + Logback,这是推荐组合:
- SLF4J:日志门面,统一接口。
- Logback:高性能、功能丰富的实现,支持异步日志、条件配置、JSON 输出等。
- 避免直接使用
System.out.println()或java.util.logging。
✅ 建议:始终通过
org.slf4j.Logger编写日志,不要引入多个日志实现(如同时引入 Log4j2 和 Logback)。
private static final Logger log = LoggerFactory.getLogger(YourClass.class);
二、日志级别规范(核心)
| 级别 | 使用场景 |
|---|---|
| ERROR | 系统错误:业务异常、数据库连接失败、外部服务调用失败等。必须记录异常堆栈(关键!) |
| WARN | 潜在问题:配置缺失、降级处理、非预期但可恢复的异常(如空值处理) |
| INFO | 关键业务节点:服务启动/关闭、重要请求入口/出口、定时任务执行、状态变更等 |
| DEBUG | 开发/测试阶段详细信息:方法入参、中间变量、SQL(非生产) |
| TRACE | 极细粒度(极少用),如循环内部状态 |
📌 重要原则:
- 生产环境通常开启 INFO 级别,禁止在生产记录 DEBUG 日志(除非临时开启)。
- ERROR 必须带异常堆栈;INFO/WARN 一般不带堆栈(除非有助于分析)。
- 不要滥用 ERROR:业务校验失败(如用户输入错误)应记录为 WARN 或 INFO,而非 ERROR。
三、日志内容格式规范(结构化日志)
推荐格式(结构化、可解析):
[时间] [traceId] [spanId] [线程名] [日志级别] [类名] [方法名] - [结构化消息]
Spring Cloud Sleuth 默认注入
traceId和spanId,便于链路追踪。
示例(使用 MDC 实现):
2025-11-20T10:30:45.123+08:00 [traceId=abcd1234] [spanId=efgh5678] [http-nio-8080-exec-1] INFO c.e.s.service.PolicyService - Create policy request received, userId=U123456, productId=P789
✅ 关键字段建议包含:
- traceId / spanId:用于分布式链路追踪(Sleuth/Zipkin)
- userId / requestId / orderId 等业务关键标识(通过 MDC 注入)
- 关键入参/出参(脱敏后)
- 耗时(如
took 120ms)
四、MDC(Mapped Diagnostic Context)最佳实践
MDC 是 SLF4J 提供的线程绑定上下文,用于在日志中注入动态字段(如用户ID、请求ID)。
示例:在 WebFilter 中设置 MDC
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MdcFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
try {
String requestId = UUID.randomUUID().toString();
MDC.put("requestId", requestId);
// 若使用 Spring Cloud Sleuth,traceId/spanId 自动注入
chain.doFilter(request, response);
} finally {
MDC.clear(); // 必须清理,避免线程池污染
}
}
}
⚠️ 警告:在异步线程(如
@Async、CompletableFuture)中,MDC 不会自动传递!需手动继承或使用TransmittableThreadLocal(阿里开源)。
五、日志内容书写准则
✅ 推荐做法:
- 使用 占位符
{},而非字符串拼接(避免性能浪费):log.info("Processing order {}, amount: {}", orderId, amount); - 记录关键状态变更:如“保单状态从A变更为B”。
- 入口/出口日志:Controller 入口记录请求参数(脱敏),出口记录结果或耗时。
- 异常日志必须包含上下文:
log.error("Failed to create policy for user {}, product {}", userId, productId, exception);
❌ 禁止做法:
- 记录敏感信息:身份证号、手机号、银行卡号(必须脱敏或禁止记录)。
- 在循环内打日志(性能杀手)。
- 使用模糊描述:“出错了”、“失败了” → 应明确“数据库连接超时”、“用户余额不足”。
- 日志中包含大对象(如整个 JSON 请求体),应只记录关键字段。
六、日志配置(Logback 示例)
src/main/resources/logback-spring.xml:
<configuration>
<!-- 控制台输出(开发) -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp/>
<logLevel/>
<loggerName/>
<message/>
<mdc/> <!-- 包含 MDC 字段 -->
<stackTrace/>
</providers>
</encoder>
</appender>
<!-- 文件输出(生产建议用 JSON 格式,便于 ELK 采集) -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp/>
<logLevel/>
<loggerName/>
<message/>
<mdc/>
<stackTrace/>
</providers>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
🔧 依赖(JSON 编码器):
<dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> <version>7.4</version> </dependency>
七、与 Spring Cloud 集成
- Sleuth 自动注入
traceId/spanId到 MDC,无需手动。 - 配合 Zipkin / SkyWalking 实现全链路追踪。
- 日志采集建议使用 Filebeat → Kafka → Logstash → ES → Kibana(ELK)或 Loki + Grafana。
八、安全与合规建议(尤其适用于金融/保险)
- 禁止记录 PII(个人身份信息):如身份证、手机号、银行卡。若必须记录,需加密或脱敏(如
138****1234)。 - 日志文件权限控制:仅限应用用户读写。
- 日志保留策略:符合公司或行业合规要求(如保留 180 天)。
- 审计日志(Audit Log)应单独记录,不可与应用日志混用。
九、总结:日志书写 Checklist
- 使用 SLF4J + Logback
- 合理使用日志级别(ERROR 带堆栈,INFO 不滥用)
- 关键业务标识(userId, orderId)通过 MDC 注入
- 使用占位符
{},避免字符串拼接 - 敏感信息脱敏或禁止记录
- 生产环境关闭 DEBUG
- 日志结构化(推荐 JSON 格式)
- 异步线程中正确传递 MDC
- 配合 Sleuth 实现 traceId 追踪
- 日志文件轮转 + 保留策略
grep 排查容器日志完整指南
grep 常用参数说明
# 基础参数
-i # 忽略大小写
-v # 反向选择,显示不包含模式的行
-n # 显示行号
-c # 统计匹配行数
-A NUM # 显示匹配行及后面NUM行
-B NUM # 显示匹配行及前面NUM行
-C NUM # 显示匹配行及前后各NUM行
-E # 使用扩展正则表达式
-F # 固定字符串匹配(不解析正则)
-r # 递归搜索目录
-w # 全词匹配
1. 基础日志搜索
1.1 简单错误搜索
# 搜索包含 ERROR 的日志行
grep "ERROR" /path/to/container.log
# 搜索错误日志并显示行号(方便定位)
grep -n "ERROR" /path/to/container.log
# 忽略大小写搜索错误(匹配 error、Error、ERROR 等)
grep -i "error" /path/to/container.log
1.2 实时日志监控
# 实时监控容器日志中的错误(Docker环境)
docker logs -f container_name | grep "ERROR"
# 实时监控并高亮显示错误
docker logs -f container_name | grep --color=auto "ERROR"
# 监控K8s Pod日志中的异常
kubectl logs -f pod-name -n namespace | grep -i "exception"
2. 时间范围排查
2.1 按时间戳搜索
# 搜索特定时间段的日志(假设日志格式包含时间戳)
grep "2024-01-15 14:" /path/to/container.log
# 搜索今天14点到15点的错误
grep "2024-01-15 14:" /path/to/container.log | grep "ERROR"
# 搜索最近1小时的日志(结合日期命令)
grep "$(date -d '1 hour ago' '+%Y-%m-%d %H:')" /path/to/container.log
2.2 时间范围+关键词组合
# 搜索今天10点到11点之间的数据库错误
grep "2024-01-15 10:" /path/to/container.log | grep -i "database.*error"
# 搜索特定日期且包含超时的日志
grep "2024-01-15" /path/to/container.log | grep -i "timeout"
3. 上下文关联排查
3.1 查看错误上下文
# 显示错误行及后面10行(查看错误堆栈)
grep -A 10 "ERROR" /path/to/container.log
# 显示错误行及前面5行(查看错误发生前的操作)
grep -B 5 "ERROR" /path/to/container.log
# 显示错误行及前后各5行(完整上下文)
grep -C 5 "ERROR" /path/to/container.log
# 查看异常堆栈的完整信息
grep -A 20 "Exception" /path/to/container.log
3.2 请求链路追踪
# 通过 traceId 追踪完整请求链路
grep "traceId:abc123" /path/to/container.log
# 追踪特定用户的操作流水
grep "userId:12345" /path/to/container.log | head -20
# 查看订单相关所有日志(包含上下文)
grep -C 3 "orderId:1001" /path/to/container.log
4. 多条件组合搜索
4.1 与条件搜索(多个条件同时满足)
# 搜索同时包含 ERROR 和 Database 的行
grep "ERROR" /path/to/container.log | grep "Database"
# 搜索特定服务的超时错误
grep "UserService" /path/to/container.log | grep -i "timeout"
# 搜索支付失败且金额大于1000的记录
grep "PAYMENT_FAILED" /path/to/container.log | grep "amount:1[0-9]\{3\}"
4.2 或条件搜索(满足任一条件)
# 搜索 ERROR 或 WARN 日志(扩展正则)
grep -E "ERROR|WARN" /path/to/container.log
# 搜索多种异常类型
grep -E "NullPointerException|TimeoutException|SQLException" /path/to/container.log
# 搜索多个微服务的错误
grep -E "user-service|order-service|payment-service" /path/to/container.log | grep "ERROR"
4.3 排除特定内容
# 搜索 ERROR 但不包含已知的业务异常
grep "ERROR" /path/to/container.log | grep -v "BusinessException"
# 搜索异常但不包含超时类异常
grep "Exception" /path/to/container.log | grep -v "Timeout"
# 排除健康检查相关的错误
grep "ERROR" /path/to/container.log | grep -v "healthcheck"
5. 统计分析与模式识别
5.1 错误统计
# 统计错误总数
grep -c "ERROR" /path/to/container.log
# 按错误类型统计
grep "ERROR" /path/to/container.log | cut -d'|' -f3 | sort | uniq -c | sort -nr
# 统计每分钟错误数量(用于识别高峰)
grep "ERROR" /path/to/container.log | cut -d' ' -f1,2 | uniq -c
# 统计不同服务的错误分布
grep "ERROR" /path/to/container.log | grep -oE "service-[a-z]+" | sort | uniq -c
5.2 性能问题识别
# 查找执行时间超过1秒的操作
grep -E "cost:[0-9]{4,}ms" /path/to/container.log
# 搜索超时相关的日志
grep -i "timeout" /path/to/container.log
# 查找数据库慢查询
grep -E "SQL.*[0-9]{4,}ms" /path/to/container.log
# 搜索线程阻塞相关日志
grep -E "blocked|deadlock|thread.*wait" /path/to/container.log
6. 高级正则表达式搜索
6.1 复杂模式匹配
# 搜索包含数字的错误码(如 ERR_500, ERR_404)
grep -E "ERR_[0-9]{3}" /path/to/container.log
# 搜索金额格式(如 ¥1000.00, $500.50)
grep -E "[¥$][0-9]+\.[0-9]{2}" /path/to/container.log
# 搜索IP地址
grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" /path/to/container.log
# 搜索JSON格式的错误信息
grep -E '\{.*"errorCode".*"\}' /path/to/container.log
6.2 业务特定模式
# 搜索订单状态变更流水
grep -E "ORDER_STATUS.*[A-Z_]+->[A-Z_]+" /path/to/container.log
# 搜索支付相关操作(创建、成功、失败)
grep -E "PAYMENT_(CREATE|SUCCESS|FAILED)" /path/to/container.log
# 搜索用户会话相关日志(登录、登出、过期)
grep -E "SESSION_(LOGIN|LOGOUT|EXPIRED)" /path/to/container.log
7. 容器环境实战命令
7.1 Docker 容器日志排查
# 查看容器最近100行日志
docker logs --tail=100 container_name
# 实时监控并过滤错误
docker logs -f container_name | grep --color=auto -E "ERROR|Exception"
# 搜索特定时间段的容器日志
docker logs --since "2024-01-15T10:00:00" --until "2024-01-15T11:00:00" container_name | grep "ERROR"
# 导出容器日志到文件再分析
docker logs container_name > container.log 2>&1
grep -n "ERROR" container.log
7.2 Kubernetes 环境排查
# 查看Pod最新日志并搜索错误
kubectl logs pod-name -n namespace | grep -i "error"
# 实时监控Pod日志(多容器时指定容器)
kubectl logs -f pod-name -c container-name -n namespace | grep "ERROR"
# 查看之前崩溃的Pod日志
kubectl logs -p pod-name -n namespace | grep -A 10 "Exception"
# 查看Deployment所有Pod的日志
kubectl logs -l app=your-app -n namespace --tail=50 | grep -E "ERROR|WARN"
# 搜索特定命名空间中所有Pod的错误
kubectl logs --all-containers=true -n namespace --since=1h | grep -c "ERROR"
7.3 多文件搜索(日志轮转情况)
# 搜索当前目录所有.log文件
grep -r "ERROR" ./*.log
# 搜索压缩的旧日志文件
zgrep "ERROR" /path/to/container.log.1.gz
# 搜索多个日志文件并显示文件名
grep -H "ERROR" /path/to/container.log*
# 跨多个文件统计错误
grep -h "ERROR" /path/to/container.log* | wc -l
8. 问题排查工作流示例
8.1 性能问题排查流程
# 1. 首先确认是否有错误
grep -c "ERROR" /path/to/container.log
# 2. 查看错误类型分布
grep "ERROR" /path/to/container.log | cut -d'|' -f3 | sort | uniq -c
# 3. 搜索超时和慢查询
grep -E "timeout|TIMEOUT|slow|SLOW" /path/to/container.log
# 4. 查看高耗时操作
grep -E "cost:[0-9]{4,}ms" /path/to/container.log | sort -k5 -nr
# 5. 分析特定时间段的性能
grep "2024-01-15 14:" /path/to/container.log | grep -E "cost:[5-9][0-9]{2,}ms"
8.2 业务异常排查流程
# 1. 通过业务ID追踪
grep "orderId:1001" /path/to/container.log
# 2. 查看完整请求链路
grep -C 5 "traceId:abc123" /path/to/container.log
# 3. 搜索异常堆栈
grep -A 15 "NullPointerException" /path/to/container.log
# 4. 查看相关服务调用
grep -E "user-service|inventory-service|payment-service" /path/to/container.log | grep -C 2 "orderId:1001"
8.3 系统问题排查流程
# 1. 检查系统级错误
grep -E "OutOfMemoryError|StackOverflowError|MemoryError" /path/to/container.log
# 2. 查看资源相关错误
grep -E "connection pool|thread pool|database connection" /path/to/container.log
# 3. 搜索死锁和线程问题
grep -i "deadlock|thread.*blocked" /path/to/container.log
# 4. 检查外部依赖状态
grep -E "redis|mysql|rabbitmq|kafka" /path/to/container.log | grep -i "error\|timeout"
9. 实用脚本示例
9.1 错误报告生成脚本
#!/bin/bash
# error_report.sh
LOG_FILE=$1
REPORT_FILE="error_report_$(date +%Y%m%d_%H%M%S).txt"
echo "=== 错误统计报告 ===" > $REPORT_FILE
echo "生成时间: $(date)" >> $REPORT_FILE
echo "日志文件: $LOG_FILE" >> $REPORT_FILE
echo "" >> $REPORT_FILE
# 错误总数
echo "错误总数: $(grep -c "ERROR" $LOG_FILE)" >> $REPORT_FILE
# 错误类型分布
echo "" >> $REPORT_FILE
echo "错误类型分布:" >> $REPORT_FILE
grep "ERROR" $LOG_FILE | cut -d'|' -f3 | sort | uniq -c | sort -nr >> $REPORT_FILE
# 最近10个错误详情
echo "" >> $REPORT_FILE
echo "最近10个错误详情:" >> $REPORT_FILE
grep -A 2 "ERROR" $LOG_FILE | tail -30 >> $REPORT_FILE
echo "报告已生成: $REPORT_FILE"
9.2 实时监控脚本
#!/bin/bash
# monitor_errors.sh
CONTAINER_NAME=$1
LOG_FILE="/tmp/container_monitor_$(date +%Y%m%d_%H%M%S).log"
echo "开始监控容器: $CONTAINER_NAME"
echo "日志输出: $LOG_FILE"
docker logs -f $CONTAINER_NAME 2>&1 | while read line; do
# 记录所有日志到文件
echo "$line" >> $LOG_FILE
# 实时显示错误和警告
if echo "$line" | grep -E "ERROR|WARN" > /dev/null; then
echo "$(date '+%Y-%m-%d %H:%M:%S') - $line"
fi
done
这些 grep 命令覆盖了生产环境容器日志排查的绝大多数场景,通过组合使用可以高效定位各种问题。
759

被折叠的 条评论
为什么被折叠?



