🧠 图解记忆:用 Trace ID 串联任务、模型和工具,再以日志、链路与指标共同解释结果;点击图片可查看原图。
**核心指标分类:**| 类别 | 指标 | 采集方式 |
|---|---|---|
| 任务级 | 任务成功率、任务耗时、中断率 | trace_id 串联 |
| 模型级 | Token 消耗、TTFT、首 Token 延迟 | API 埋点 |
| 工具级 | 工具调用成功率、工具响应时间、工具误调用率 | 工具拦截器 |
| Agent 级 | 循环检测率、规划步数、上下文膨胀率 | Agent 状态机 |
| 成本级 | 单任务成本、日成本、月成本、ROI | 计费日志 |
可观测性三大支柱:
1. Logging(日志)
→ 结构化日志:trace_id / span_id / event_type
→ 关键事件:工具调用/结果/异常/重试
2. Tracing(链路追踪)
→ OpenTelemetry 串联全链路
→ LangSmith / Phoenix 自动可视化
3. Metrics(指标)
→ Prometheus 聚合 + Grafana 展示
→ 告警规则:SLO / SLA生产级代码示例:
展开 Python 代码示例(49 行)
python
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.resources import Resource
# 创建 tracer
resource = Resource.create({"service.name": "agent-service"})
provider = TracerProvider(resource=resource)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)
class ObservableAgent:
def __init__(self, llm, tools, callbacks=None):
self.llm = llm
self.tools = tools
self.callbacks = callbacks or []
async def run(self, task: str) -> str:
with tracer.start_as_current_span("agent_run") as span:
span.set_attribute("task", task)
span.set_attribute("user_id", get_current_user())
# 1. 规划阶段
with tracer.start_as_current_span("planning") as plan_span:
plan = await self.plan(task)
plan_span.set_attribute("plan_steps", len(plan))
# 2. 执行阶段(每个步骤一个 span)
results = []
for i, step in enumerate(plan):
with tracer.start_as_current_span(f"step_{i}") as step_span:
step_span.set_attribute("step_type", step["type"])
step_span.set_attribute("step_description", step["desc"])
result = await self.execute_step(step)
# 检测循环
if self.is_looping(results, step):
step_span.set_attribute("loop_detected", True)
span.set_attribute("had_loop", True)
raise LoopDetectedError("Agent appears to be looping")
results.append(result)
step_span.set_attribute("success", True)
span.set_attribute("total_steps", len(results))
span.set_attribute("total_tokens", self.get_token_count())
return self.summarize(results)面试话术:
示例表达(仅在能用本人经历或可复现实验佐证时使用): "Agent 可观测性核心是 trace_id 串联。我设计时用 OpenTelemetry 的 span 嵌套结构:最外层是 agent_run,内层分 planning 和各个 step,每个 step 里记录 tool_call。每个 span 都打上 user_id、model、token_count 属性。出问题后用 trace_id 在 LangSmith 或 Jaeger 里一键拉出完整链路,哪个 step 耗时最长、哪个工具失败了,一目了然。"
