SkyWalking UI 深度探索:Logs(日志集成与链路关联)
SkyWalking实现可观测性闭环的关键在于日志与TraceID的关联。通过配置Agent和修改日志格式添加%X{traceId}占位符,可以将分散的微服务日志与调用链关联。在UI中支持双向跳转:从Trace查看关联日志,或通过traceId反向查询链路。这种集成使故障排查从"现象→链路→日志→根因"形成闭环,无需多服务器手动grep,显著提升效率。最佳实践包括统一日志格式、
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 页面跳转(最常用)
- 进入 Trace 页面
- 找到一条失败或慢请求
- 点击某个 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。
排查步骤:
-
进入 Trace 页面
- 查找
gateway
服务的错误请求 - 找到一条耗时 1.8s、状态为 error 的 trace
- 查找
-
查看调用链
- 发现
payment-service
的 Span 报错 - 错误信息:
RemoteServiceTimeout
- 发现
-
点击“View Logs”
- 跳转到 Logs 页面,自动带入
traceId=abc123...
- 跳转到 Logs 页面,自动带入
-
查看 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
-
结论:
第三方支付接口响应超时,导致下单失败。
-
动作:
- 通知支付团队优化接口
- 本地增加超时降级逻辑
✅ 整个过程无需登录服务器、无需 grep 日志,全部在 UI 中完成!
七、最佳实践
项目 | 建议 |
---|---|
📦 日志格式 | 统一规范,必须包含 %X{traceId} |
🧩 多语言支持 | Java(MDC)、Go(zap + context)、Node.js(cls-hooked)等需对应实现 |
🔐 敏感信息 | 避免在日志中打印密码、身份证等,可使用日志脱敏 |
📁 存储策略 | 日志量大,建议设置 Elasticsearch 的 TTL(如保留 7 天) |
🔄 采样策略 | 高流量服务可对日志采样,避免性能开销 |
✅ 总结:日志关联使用口诀
“一配日志格式,二加 traceId,三查调用链,四看关联日志”
Logs + Tracing 的结合,让你实现:
“从现象 → 链路 → 日志 → 根因” 的一站式闭环排查
更多推荐
所有评论(0)