feat(observability): slog 日志带 trace_id,与链路双向互跳

新增 sundynix-shared/otelx/slog.go:traceHandler 包装 slog.Handler,凡 ctx 有
活跃 span 的 slog.InfoContext(ctx,...) 自动注入 trace_id/span_id;SetupSlog(服务名)
装全局 JSON slog(service 标签 + LOG_LEVEL 控级)并设默认;TraceID(ctx) 辅助取 hex。

- 三个服务 main 启动调 otelx.SetupSlog。
- gateway 访问日志 Observe() 改用 slog.InfoContext(c.Request.Context(),...)(删旧
  accessLogger)→ 每条 HTTP 日志带 trace_id。
- dispatcher orchestrator.Handle 的 received/done/error 改 ctx-aware slog → 任务
  执行日志带 trace_id。
- otelx 单测 5 例(注入/无 span 不注入/With() 后仍生效/级别解析)。
- production_readiness.md 1.1:可观测性三件套(metrics+logs带trace_id+traces)闭环。

验证:dispatcher「task done」日志 trace_id 拿去 Jaeger /api/traces/<id> 命中同一条
11 span/3 服务链路;gateway 访问日志亦带同一 trace_id。四模块 build+vet+test 全绿。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-06-24 12:41:33 +08:00
parent f37d046f2c
commit 218fba559c
8 changed files with 154 additions and 11 deletions
+3 -1
View File
@@ -37,7 +37,9 @@
- **Eino 图埋点**`task.execute` → 每个 `node.<kind>``tool.call`/`tool.serve`(跨服务成对)→ `llm.stream`/`llm.generate`,层级与 ExecEvent 对齐。
- 实测一次「input→retriever→agent」任务出 14 span / 3 服务,瓶颈(kb_search 692ms、llm 1597ms)一眼可见。
> 与既有 Prometheusmetrics+ sloglogs)合为可观测性三件套。下一步可补:slog 日志带 trace_id 互跳、mcp-py 接入、采样策略
- **日志 ↔ 链路互跳**`otelx.SetupSlog(服务名)` 安装链路感知的全局 slogJSON + service 标签),`traceHandler` 让任意 `slog.InfoContext(ctx,...)` 自动带 `trace_id`/`span_id`。gateway 访问日志、dispatcher 任务生命周期日志均已带 trace_id——Jaeger 里拿 trace_id 即可过滤日志,反之从报错日志跳回链路。实测一致命中
> Prometheusmetrics+ sloglogs,带 trace_id+ OTeltraces)= 可观测性三件套已闭环。下一步可补:mcp-py 接入、采样策略、legacy log.Printf 渐进迁移到 ctx-aware slog。
**实现细节(原规划,已照此落地)**