跳到主要内容

可观测性指南

云开发提供内置的可观测性能力,基于 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 导出

本地开发时,使用 ConsoleTraceConfigExporterType.Console 即可实时查看追踪数据,无需配置外部服务。

2. 生产环境使用 OTLP 导出

生产环境建议将追踪数据导出到 Langfuse、Jaeger 等专业平台,便于长期存储和查询分析。

相关资源