可观测性指南
云开发提供内置的可观测性能力,基于 OpenTelemetry 和 OpenInference 标准,帮助开发者追踪和监控 AI Agent 的完整执行链路。
前置条件
- 已创建 Agent 应用(LangChain / LangGraph / CrewAI)
- 已安装对应 SDK(
cloudbase-agent-server/@cloudbase/agent-server) - 了解 OpenTelemetry 基本概念(可选)
安装依赖
# 基础依赖
pip install cloudbase-agent-server cloudbase-agent-observability
# 如需导出到 OTLP 后端(如 Langfuse)
pip install opentelemetry-exporter-otlp
# 基础依赖
npm install @cloudbase/agent-server @cloudbase/agent-observability
# 如需导出到 OTLP 后端
npm install @opentelemetry/exporter-trace-otlp-http
概述
什么是可观测性
可观测性(Observability)是指通过系统输出的信号(日志、指标、追踪)来理解系统内部状态的能力。对于 AI Agent 应用,可观测性可以帮助你:
- 追踪执行链路:查看 Agent 从接收请求到返回响应的完整调用链
- 定位性能瓶颈:识别耗时较长的 LLM 调用或工具执行
- 调试问题:分析 Agent 的决策过程和工具调用参数
- 优化成本:统计 Token 使用量,分析模型调用频率
可观测性特点
- 开箱即用:无需复杂配置,一行代码或一个环境变量即可开启
- 全链路追踪:自动串联 Server 层 → Adapter 层 → Agent SDK 层的调用链路
- 标准化:遵循 OpenTelemetry 和 OpenInference 语义约定
- 多导出目标:支持控制台输出(调试)和 OTLP 导出(Langfuse、Jaeger 等)
架构原理
Span 层次结构示例
以 LangGraph 工作流为例,典型的 Span 层次结构如下:
AG-UI.Server (Request entry point)
└─ Adapter.LangGraph (Agent adapter layer)
└─ LangGraph
├─ node_a (LangGraph node)
│ └─ ChatOpenAI (LLM call)
├─ node_b (LangGraph node)
│ ├─ ChatOpenAI (LLM call)
│ └─ calculator (Tool call)
└─ synthesizer (LangGraph node)
└─ ChatOpenAI (LLM call)
Span 类型说明
| 类型 | 图标 | 说明 | 示例 |
|---|---|---|---|
CHAIN | ⛓️ | 链式调用 | Adapter.LangGraph、LangGraph 节点 |
LLM | 💬 | LLM 调用 | ChatOpenAI、ChatAnthropic |
TOOL | 🔧 | 工具调用 | calculator、get_weather |
AGENT | 🤖 | Agent 调用 | 多 Agent 编排场景 |
遵循的标准
- OpenTelemetry:分布式追踪的标准框架,提供 Span、Trace、Context 等概念
- OpenInference:AI 应用的语义约定,定义了 LLM、TOOL、CHAIN 等 Span 类型的属性规范
关键属性包括:
input.value/output.value:输入输出内容llm.model_name:模型标识llm.token_count.prompt/llm.token_count.completion:Token 使用量tool.name:工具函数名称
快速开始
方式一:环境变量开启(推荐)
这是最简单的方式,无需修改任何代码,只需设置环境变量即可开启可观测性。
# 开启控制台输出(适合本地开发调试)
AUTO_TRACES_STDOUT=true
# 关闭可观测性
AUTO_TRACES_STDOUT=false
示例:
# app.py - 无需修改代码
from cloudbase_agent.server import AgentServiceApp
from cloudbase_agent.langgraph import LangGraphAgent
app = AgentServiceApp() # 自动读取 AUTO_TRACES_STDOUT 环境变量
app.run(lambda: {"agent": agent})
// index.js - 无需修改代码
import { createExpressRoutes } from "@cloudbase/agent-server";
createExpressRoutes({
createAgent,
express: app,
// observability 参数不传,自动读取 AUTO_TRACES_STDOUT 环境变量
});
方式二:代码配置开启
如需更精细的控制(如配置 OTLP 导出),可以通过代码显式配置。
from cloudbase_agent.server import AgentServiceApp
from cloudbase_agent.observability.server import ConsoleTraceConfig, OTLPTraceConfig
# 方式 A:控制台输出(本地调试)
app = AgentServiceApp(observability=ConsoleTraceConfig())
# 方式 B:导出到 Langfuse
app = AgentServiceApp(
observability=OTLPTraceConfig(
endpoint="https://your-langfuse.com/api/public/otel/v1/traces",
headers={"Authorization": "Basic your-credentials"}
)
)
app.run(lambda: {"agent": agent})
import { createExpressRoutes } from "@cloudbase/agent-server";
import { ExporterType } from "@cloudbase/agent-observability/server";
// 方式 A:控制台输出(本地调试)
createExpressRoutes({
createAgent,
express: app,
observability: { type: ExporterType.Console }
});
// 方式 B:导出到 OTLP 后端
createExpressRoutes({
createAgent,
express: app,
observability: {
type: ExporterType.OTLP,
url: "https://your-langfuse.com/api/public/otel/v1/traces",
headers: { "Authorization": "Basic your-credentials" }
}
});
导出器配置
Console 导出(本地调试)
控制台导出器将 Span 信息以 JSON 格式输出到控制台,适合本地开发和调试。
输出示例:
{
"trace_id": "550e8400-e29b-41d4-a716-446655440000",
"span_id": "a1b2c3d4e5f67890",
"parent_span_id": "0987654321fedcba",
"name": "ChatOpenAI",
"kind": "SPAN_KIND_INTERNAL",
"start_time": "2025-01-15T08:30:00.123456Z",
"end_time": "2025-01-15T08:30:01.234567Z",
"attributes": {
"openinference.span.kind": "LLM",
"llm.model_name": "gpt-4",
"input.value": "Hello, how are you?",
"output.value": "I'm doing well, thank you!",
"llm.token_count.prompt": 5,
"llm.token_count.completion": 7
}
}
查看技巧:
# 保存到文件
python app.py 2>&1 | grep "^\\{" > spans.jsonl
# 解析并美化输出
python app.py 2>&1 | python -m json.tool
OTLP 导出(生产环境)
OTLP(OpenTelemetry Protocol)是 OpenTelemetry 的标准传输协议,可以将追踪数据导出到各种后端,如 Langfuse、Jaeger、Zipkin 等。
Langfuse 配置示例
Langfuse 是一个开源的 LLM 可观测性平台,原生支持 OpenTelemetry。
from cloudbase_agent.observability.server import OTLPTraceConfig
app = AgentServiceApp(
observability=OTLPTraceConfig(
endpoint="https://cloud.langfuse.com/api/public/otel/v1/traces",
headers={
"Authorization": "Basic " + base64.b64encode(
f"{public_key}:{secret_key}".encode()
).decode()
}
)
)
import { ExporterType } from "@cloudbase/agent-observability/server";
createExpressRoutes({
createAgent,
express: app,
observability: {
type: ExporterType.OTLP,
url: "https://cloud.langfuse.com/api/public/otel/v1/traces",
headers: {
"Authorization": `Basic ${Buffer.from(`${publicKey}:${secretKey}`).toString("base64")}`
}
}
});
Jaeger 配置示例
Jaeger 是 Uber 开源的分布式追踪系统。
from cloudbase_agent.observability.server import OTLPTraceConfig
app = AgentServiceApp(
observability=OTLPTraceConfig(
endpoint="http://localhost:4318/v1/traces"
)
)
createExpressRoutes({
createAgent,
express: app,
observability: {
type: ExporterType.OTLP,
url: "http://localhost:4318/v1/traces"
}
});
完整示例
Python + LangGraph + Langfuse
import os
import base64
from cloudbase_agent.server import AgentServiceApp
from cloudbase_agent.langgraph import LangGraphAgent
from cloudbase_agent.observability.server import OTLPTraceConfig
from langgraph.graph import StateGraph, MessagesState
from langchain_openai import ChatOpenAI
# 创建 Agent
def create_agent():
model = ChatOpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL"),
model="gpt-4"
)
async def chat_node(state):
response = await model.ainvoke(state["messages"])
return {"messages": [response]}
workflow = StateGraph(MessagesState)
workflow.add_node("chat", chat_node)
workflow.add_edge("__start__", "chat")
workflow.add_edge("chat", "__end__")
return {
"agent": LangGraphAgent(
name="chatbot",
graph=workflow.compile()
)
}
# 配置 Langfuse
credentials = base64.b64encode(
f"{os.getenv('LANGFUSE_PUBLIC_KEY')}:{os.getenv('LANGFUSE_SECRET_KEY')}".encode()
).decode()
app = AgentServiceApp(
observability=OTLPTraceConfig(
endpoint=f"{os.getenv('LANGFUSE_HOST')}/api/public/otel/v1/traces",
headers={"Authorization": f"Basic {credentials}"}
)
)
app.run(create_agent)
TypeScript + LangGraph + Console
import { createExpressRoutes } from "@cloudbase/agent-server";
import { LanggraphAgent } from "@cloudbase/agent-adapter-langgraph";
import { StateGraph, Annotation } from "@langchain/langgraph";
import { ChatOpenAI } from "@langchain/openai";
import express from "express";
import { ExporterType } from "@cloudbase/agent-observability/server";
const app = express();
const createAgent = () => {
const model = new ChatOpenAI({
modelName: "gpt-4",
openAIApiKey: process.env.OPENAI_API_KEY,
});
const StateAnnotation = Annotation.Root({
messages: Annotation<string[]>({
reducer: (x, y) => x.concat(y),
default: () => [],
}),
});
const graph = new StateGraph(StateAnnotation)
.addNode("chat", async (state) => {
const response = await model.invoke(state.messages);
return { messages: [response.content] };
})
.addEdge("__start__", "chat")
.addEdge("chat", "__end__");
return {
agent: new LanggraphAgent({
name: "chatbot",
compiledWorkflow: graph.compile(),
}),
};
};
createExpressRoutes({
createAgent,
express: app,
observability: { type: ExporterType.Console },
});
app.listen(9000);
最佳实践
1. 开发环境使用 Console 导出
本地开发时,使用 ConsoleTraceConfig 或 ExporterType.Console 即可实时查看追踪数据,无需配置外部服务。
2. 生产环境使用 OTLP 导出
生产环境建议将追踪数据导出到 Langfuse、Jaeger 等专业平台,便于长期存储和查询分析。