feat(observability): OpenTelemetry 全链路追踪(Jaeger + NATS 跨总线传播)
新增 sundynix-shared/otelx:otelx.Init(ctx,服务名) 注册 W3C 传播器 + OTLP/HTTP 批量导出(默认 localhost:4318,docker 里的 Jaeger);OTEL_SDK_DISABLED=true 关导出。 Jaeger 不在线 / 导出器构建失败都不阻断启动(可观测性是增益而非依赖)。 - NATS 跨进程传播(无现成中间件):bus/trace.go 的 natsHeaderCarrier + inject/extract, PublishTask/CallTool 注入 traceparent,ConsumeTasks/ServeTool 抽出续上 → 链路跨总线连成一棵树。 - 埋点:gateway 挂 otelgin(HTTP server span,链路根);dispatcher task.execute → node.<kind>(每节点,nctx 下传使工具/LLM 挂到节点下)→ llm.stream/llm.generate; bus 自动出 tool.call(client)↔tool.serve(server) 成对跨服务 span。 - docker-compose 加 jaeger all-in-one(UI :16686,OTLP :4318)。 - 依赖修复:otlptracehttp 触发 genproto 单体(旧)vs 拆分模块 ambiguous import(milvus 拉旧版), pin genproto 至后拆分版(go.work 工作区全局生效)。 - production_readiness.md 1.1 更新为「已实现」。 验证:真实 input→retriever→agent 任务在 Jaeger 出 14 span / 3 服务的完整树, 跨 NATS(publish→consume)、跨服务(tool.call→tool.serve)均连通, 瓶颈 kb_search 692ms、llm 1597ms 一眼可见;四模块 build+vet+test 全绿。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package bus
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// natsHeaderCarrier 让 OTel 传播器能读写 NATS 消息头(W3C traceparent 等),
|
||||
// 从而把链路上下文跨 NATS 总线带到下游服务——这是分布式追踪能连成一棵树的关键。
|
||||
type natsHeaderCarrier nats.Header
|
||||
|
||||
func (c natsHeaderCarrier) Get(key string) string { return nats.Header(c).Get(key) }
|
||||
func (c natsHeaderCarrier) Set(key, value string) { nats.Header(c).Set(key, value) }
|
||||
func (c natsHeaderCarrier) Keys() []string {
|
||||
out := make([]string, 0, len(c))
|
||||
for k := range c {
|
||||
out = append(out, k)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// injectTrace 把 ctx 里的链路上下文写进 NATS 消息头(发布前调用)。
|
||||
func injectTrace(ctx context.Context, h nats.Header) {
|
||||
otel.GetTextMapPropagator().Inject(ctx, natsHeaderCarrier(h))
|
||||
}
|
||||
|
||||
// extractTrace 从 NATS 消息头还原上游链路上下文,挂到 ctx 上(消费时调用)。
|
||||
func extractTrace(ctx context.Context, h nats.Header) context.Context {
|
||||
if h == nil {
|
||||
return ctx
|
||||
}
|
||||
return otel.GetTextMapPropagator().Extract(ctx, natsHeaderCarrier(h))
|
||||
}
|
||||
|
||||
// tracer 是 bus 自身的 span 发射器(与业务同 scope,方便 Jaeger 归组)。
|
||||
func tracer() trace.Tracer {
|
||||
return otel.Tracer("github.com/sundynix/sundynix-agentix")
|
||||
}
|
||||
Reference in New Issue
Block a user