日志排查与分析
问题
线上出现异常/告警,如何通过日志快速定位问题?ELK 日志系统怎么用?
答案
日志排查基本功
Linux 日志排查常用命令
# 实时查看日志
tail -f app.log
# 查看最近 100 行
tail -100 app.log
# 搜索错误日志
grep -i "error\|exception" app.log | tail -20
# 按时间范围查找
grep "2024-01-15 10:2[0-9]" app.log
# 统计错误次数
grep "ERROR" app.log | wc -l
# 统计错误类型排名
grep "Exception" app.log | awk -F: '{print $NF}' | sort | uniq -c | sort -rn | head 10
# 查看某个请求的完整日志(按 TraceId)
grep "trace-id-12345" app.log
结构化日志
Logback JSON 格式配置
// 结构化日志比纯文本更利于 ELK 检索
{
"timestamp": "2024-01-15T10:23:45.123",
"level": "ERROR",
"logger": "c.e.s.OrderService",
"message": "创建订单失败",
"traceId": "abc-123-xyz",
"userId": "10086",
"orderId": "ORD20240115001",
"exception": "java.lang.NullPointerException",
"stackTrace": "..."
}
logback-spring.xml JSON 输出
<appender name="JSON" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"app":"order-service","env":"prod"}</customFields>
</encoder>
</appender>
ELK 日志系统
Kibana 常用查询语法(KQL)
# 查询某个 TraceId
traceId: "abc-123-xyz"
# 查询错误日志
level: "ERROR"
# 组合查询
level: "ERROR" AND app: "order-service" AND message: "创建订单失败"
# 时间范围
@timestamp >= "2024-01-15T10:00:00" AND @timestamp <= "2024-01-15T11:00:00"
# 模糊查询
message: *timeout*
链路追踪 + 日志
MDC 传递 TraceId
// 拦截器:请求进入时设置 TraceId
public class TraceInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, ...) {
String traceId = request.getHeader("X-Trace-Id");
if (traceId == null) traceId = UUID.randomUUID().toString();
MDC.put("traceId", traceId);
return true;
}
@Override
public void afterCompletion(...) {
MDC.clear();
}
}
日志模板中使用 TraceId
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] %-5level %logger{36} - %msg%n</pattern>
告警日志分析
日志告警规则
// 1 分钟内 ERROR 超过 10 条 → 告警
// 5 分钟内同一异常超过 50 次 → 告警
// 出现 OOM / StackOverflow → 立即告警
常见面试问题
Q1: 线上问题无法复现,怎么通过日志排查?
答案:
- 拿到 TraceId → ELK 搜索完整调用链日志
- 看请求参数、中间步骤、返回值
- 看前后时间段是否有 GC / 慢 SQL / 超时
- 对比正常请求和异常请求的差异
Q2: 日志级别怎么设置?
答案:
| 级别 | 用途 | 生产环境 |
|---|---|---|
| ERROR | 影响功能的异常 | ✅ 必须 |
| WARN | 潜在问题 | ✅ 建议 |
| INFO | 关键业务流程 | ✅ 适量 |
| DEBUG | 调试信息 | ❌ 关闭 |
Q3: 日志打太多怎么办?
答案:
- 生产环境关闭 DEBUG
- 使用采样日志(每 N 条打一条)
- 异步写日志(AsyncAppender)
- 日志分级存储:ERROR 保留更久