AI 工作流的可观测性架构:Trace、Metric 与 Log 的三维性能诊断体系
一、可观测性在 AI 工作流中的必要性
AI 工作流的复杂性与传统微服务有本质区别。一个典型的 Agent 调用链可能涉及:用户意图解析 → RAG 检索 → 多轮 LLM 推理 → 工具调用 → 结果聚合 → 流式输出。这条链路上,延迟的累积不是线性的——一个工具调用的超时可能引发后续节点的重试风暴,一个 Prompt 的长度膨胀可能让 Token 成本翻倍。
传统监控的痛点在于:Metrics 能告诉你 P99 延迟变高了,但不知道是哪个环节在拖后腿;Log 记录了每个节点的输出,却无法关联到具体的用户请求;Trace 有父子 Span 关系,但 LLM 调用的耗时不等于"网络延迟 + 推理时间",中间还有 Tokenization、KV Cache 查找等不可观测的步骤。
三维可观测性体系的核心思路是:Metrics 发现问题,Trace 定位环节,Log 还原现场。
graph TD
A[告警触发: P99 延迟 > 5s] --> B{Metrics 面板}
B --> C[推理耗时占比 80%]
B --> D[工具调用耗时占比 50%]
C --> E[Trace 下钻到具体 Span]
D --> E
E --> F[定位到特定 Prompt 模板]
E --> G[定位到特定 Tool API]
F --> H[Log 查看完整 Prompt 内容]
G --> I[Log 查看 API 返回]
H --> J[优化 Prompt 长度 / 切换模型]
I --> K[增加缓存 / 切换供应商]
二、Trace 设计:从链路追踪到语义追踪
标准 OpenTelemetry Span 的属性是针对 HTTP/RPC 调用设计的,对于 LLM 调用需要扩展自定义属性。建议按以下维度设计 Span:
// LLM 调用的自定义 Span 属性
type LLMSpanAttributes struct {
Model string // gpt-4o-mini
Provider string // openai
PromptTokens int
CompletionTokens int
TotalTokens int
Temperature float64
StopReason string // stop | length | tool_calls
FirstTokenLatency time.Duration // TTFT
StreamMode bool
ToolCallsCount int
CacheHit bool // 是否命中 Prompt Cache
}
关键设计原则:
Span 的父子关系要反映语义依赖,而非物理调用时序。如果一个 Agent 先做查询改写再检索,两个 LLM 调用应该是串行的父子 Span;但如果做并行工具调用(同时查天气、查日历),它们应该是同一个父 Span 下的兄弟 Span。
区分"排队延迟"和"执行延迟"。LLM API 调用中,从发起请求到收到第一个 Token 的时间(TTFT)包含排队时间,这往往是供应商侧的瓶颈。通过记录
ttft和tokens_per_second可以判断:
P99 延迟高 + TTFT 高 → 供应商排队拥塞,考虑切换供应商或增加并发限制
P99 延迟高 + tokens_per_second 低 → 模型推理慢,考虑切换更快的模型
P99 延迟高 + 两者都正常 → 业务逻辑耗时多,优化 Prompt 或减少 Tool 调用轮次
三、Metrics 设计:从基础设施指标到业务指标
基础设施层面的 Metrics(CPU、内存、GC 暂停)是必要但不充分的。AI 工作流需要额外的业务视角:
// 业务 Metrics 的设计维度
const businessMetrics = {
// 质量指标
task_success_rate: { type: 'gauge', labels: ['agent_type', 'workflow_id'] },
tool_call_success_rate: { type: 'gauge', labels: ['tool_name'] },
// 成本指标
token_cost_per_task: { type: 'histogram', labels: ['model', 'agent_type'], buckets: [0.001, 0.01, 0.05, 0.1, 0.5] },
daily_token_cost: { type: 'counter', labels: ['model'] },
// 延迟指标
end_to_end_latency: { type: 'histogram', labels: ['agent_type'], buckets: [1, 5, 10, 30, 60, 120] },
ttft_latency: { type: 'histogram', labels: ['model', 'provider'] },
tool_execution_latency: { type: 'histogram', labels: ['tool_name'] },
// 缓存指标
semantic_cache_hit_rate: { type: 'gauge', labels: ['cache_layer'] },
cache_memory_mb: { type: 'gauge' },
// 限流指标
rate_limit_hits: { type: 'counter', labels: ['model', 'provider'] }
};
PromQL 查询示例:
# 过去 1 小时 Token 成本突增
(sum(rate(token_cost_per_task_sum[5m])) / sum(rate(token_cost_per_task_count[5m])))
> 2 * (sum(rate(token_cost_per_task_sum[1h])) / sum(rate(token_cost_per_task_count[1h])))
# 特定 Tool 调用的成功率下降
tool_call_success_rate{tool_name="search_database"} < 0.95
四、Log 设计:结构化日志与采样策略
AI 工作流的日志量可能远超传统服务:一次 Agent 对话可能产生 20+ 轮 LLM 调用,每轮都有完整的 Prompt 和 Response。全量记录所有 Prompt 内容极不经济。
分层采样策略:
Level 1(始终记录):任务 ID、Agent 类型、总耗时、Token 总消耗、成功/失败
Level 2(采样 10%):每个 LLM 调用的 Prompt 前 500 字符 + Response 前 500 字符
Level 3(按错误采样 100%,正常采样 1%):完整 Prompt + 完整 Response
Level 4(单条 Trace 按需开启):所有中间状态、向量检索结果、RAG 召回内容
实现示例:
type AIWorkflowLogger struct {
base *slog.Logger
sampler Sampler
}
func (l *AIWorkflowLogger) LogLLMCall(ctx context.Context, call LLMCallRecord) {
// Level 1: 始终记录
l.base.InfoContext(ctx, "llm_call",
"task_id", call.TaskID,
"model", call.Model,
"prompt_tokens", call.PromptTokens,
"completion_tokens", call.CompletionTokens,
"latency_ms", call.Latency.Milliseconds(),
)
// Level 2: 采样记录摘要
if l.sampler.ShouldSample(call.TaskID, 0.1) {
l.base.DebugContext(ctx, "llm_call_detail",
"prompt_preview", truncate(call.Prompt, 500),
"response_preview", truncate(call.Response, 500),
)
}
// Level 3: 错误全量 + 正常采样
if call.Error != nil || l.sampler.ShouldSample(call.TaskID, 0.01) {
l.base.DebugContext(ctx, "llm_call_full",
"prompt", call.Prompt,
"response", call.Response,
"error", call.Error,
)
}
}
五、总结
AI 工作流的可观测性不是监控工具的简单叠加,需要针对 LLM 调用、Token 消费、语义缓存等新维度设计指标体系。核心原则:Metrics 用于发现异常并触发告警,Trace 用于定位到具体的 Span 节点,Log 用于还原完整的上下文。Trace 设计要反映语义依赖而非物理时序,Metrics 要覆盖业务指标(成本、成功率、缓存命中率),Log 要用分层采样避免存储爆炸。三者协同,才能在 AI 工作流的性能迷宫中快速找到出口。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/qq_34803115/article/details/163001197



