SkyWalking 可观测性闭环的最后一环 —— Logs(日志集成)

Tracing 告诉你“请求卡在哪一步”Metrics 告诉你“系统有多忙”,而 Logs 则告诉你“具体发生了什么”

通过将 应用日志与 TraceID 关联,你可以实现真正的 “端到端、一站式”故障排查体验


📄 SkyWalking UI 深度探索:Logs(日志集成与链路关联)

📌 访问路径:UI → 左侧菜单 → “Logs”


一、为什么需要日志与 TraceID 关联?

在微服务架构中,一个请求跨越多个服务,日志分散在不同机器上。传统排查方式:

# 你得登录多台服务器,手动 grep
tail -f order.log | grep "orderId=123"
tail -f user.log | grep "orderId=123"

❌ 问题:

  • 效率低
  • 容易遗漏
  • 难以关联上下文

✅ SkyWalking 的解决方案:

所有日志带上 traceId,在 UI 中一键查询整条链路的所有日志


二、核心目标:实现“从链路到日志”的无缝跳转

场景 如何实现
🔍 在调用链中看到某个 Span 报错 点击“View Logs”直接查看该请求的日志
🧩 想看某个 trace 的完整执行过程 在 Logs 页面按 traceId 查询所有相关日志
🕵️ 排查参数传递错误 查日志确认入参、出参、中间状态

✅ 最终效果:点击一个 Trace → 看到所有服务的日志,像看单体日志一样简单


三、前置条件:如何让日志带上 TraceID?

SkyWalking 不会自动采集你的业务日志,你需要做两件事:

✅ 步骤 1:启用 SkyWalking 日志插件(Agent 配置)

确保 Agent 启用了日志采集功能,在 agent.config 或 JVM 参数中开启:

# 启用日志采集
logging.log-collector-enabled=true

# 设置日志收集模式(推荐 gRPC)
logging.mixed-log-access-log-enabled=true

或通过 JVM 参数:

-DSW_LOGGING_LOG_COLLECTOR_ENABLED=true

✅ 步骤 2:日志格式中添加 %traceId 占位符

使用 MDC(Mapped Diagnostic Context) 将 SkyWalking 的 traceId 注入日志。

Java 示例(Logback + SLF4J)

1. 修改 logback-spring.xml

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>
            %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %X{traceId} %msg%n
        </pattern>
    </encoder>
</appender>

🔑 关键:%X{traceId} 会自动填充当前链路的 TraceID

2. 代码中无需手动设置

SkyWalking Agent 会自动将 traceId 放入 MDC,你只需正常打日志:

log.info("开始创建订单, userId={}", userId);
// 输出示例:
// 2025-04-05 10:30:12 [http-nio-8080-exec-1] INFO  OrderService - abc123-def456 开始创建订单, userId=1001

四、如何在 SkyWalking UI 中使用 Logs?

方法 1:通过 Trace 页面跳转(最常用)
  1. 进入 Trace 页面
  2. 找到一条失败或慢请求
  3. 点击某个 Span → 弹出详情 → 点击 “View Logs”

✅ 效果:

自动跳转到 Logs 页面,并按该 Span 的 traceId 过滤日志


方法 2:直接在 Logs 页面查询
查询条件 说明
Trace ID 输入已知 traceId(如从日志中复制)
Service / Instance 过滤特定服务
Level ERROR、WARN、INFO 等
Keyword 搜索关键词(如 “timeout”、“null”)
Time Range 时间范围(建议先缩小)

✅ 示例:
查找 order-service 中包含 “库存不足” 且 traceId 不为空的日志。


五、日志详情页面解读

点击一条日志,会弹出详细信息:

字段 说明
Time 日志时间戳
Service / Instance 来自哪个服务和实例
Level 日志级别(ERROR/WARN/INFO)
Message 日志内容
Trace ID 关联的调用链 ID(可点击跳转到 Trace)
Tags 附加上下文(如 thread、logger)

🔗 支持双向跳转:

  • Log → Trace:点击 traceId 跳转到调用链
  • Trace → Log:点击 Span 查看相关日志

六、实战:一次完整的“端到端”排查流程

场景:

用户反馈“下单失败”,但接口返回 500。

排查步骤:
  1. 进入 Trace 页面

    • 查找 gateway 服务的错误请求
    • 找到一条耗时 1.8s、状态为 error 的 trace
  2. 查看调用链

    • 发现 payment-service 的 Span 报错
    • 错误信息:RemoteServiceTimeout
  3. 点击“View Logs”

    • 跳转到 Logs 页面,自动带入 traceId=abc123...
  4. 查看 payment-service 的日志

    2025-04-05 10:30:15 [http-nio-8080-exec-3] ERROR PaymentClient - 
    调用第三方支付超时, url=https://api.pay.com/v1/pay, cost=5000ms
    java.net.SocketTimeoutException: Read timed out
    
  5. 结论

    第三方支付接口响应超时,导致下单失败。

  6. 动作

    • 通知支付团队优化接口
    • 本地增加超时降级逻辑

✅ 整个过程无需登录服务器、无需 grep 日志,全部在 UI 中完成!


七、最佳实践

项目 建议
📦 日志格式 统一规范,必须包含 %X{traceId}
🧩 多语言支持 Java(MDC)、Go(zap + context)、Node.js(cls-hooked)等需对应实现
🔐 敏感信息 避免在日志中打印密码、身份证等,可使用日志脱敏
📁 存储策略 日志量大,建议设置 Elasticsearch 的 TTL(如保留 7 天)
🔄 采样策略 高流量服务可对日志采样,避免性能开销

✅ 总结:日志关联使用口诀

“一配日志格式,二加 traceId,三查调用链,四看关联日志”

Logs + Tracing 的结合,让你实现:

“从现象 → 链路 → 日志 → 根因” 的一站式闭环排查

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐