← 文章 / 云原生与基础设施
signoz 4小时前 · 2026-09-25 18:40:08 · 1 阅读

Vercel Eve 基于 OpenTelemetry 的可观测性与监控

eve 是 Vercel 推出的 filesystem-first 智能体开发框架。它内置了基于 OpenTelemetry 的全链路追踪,无需额外安装埋点包,每次模型调用、工具执行和子智能体派发都会自动生成一个 span。

本指南将介绍如何把交互式 eve dev 终端界面产生的追踪数据发送到 SigNoz。

什么是 Eve 可观测性?

Eve 可观测性指的是从 eve 智能体收集追踪数据,让你清楚了解每一轮对话发生了什么:经历了哪些模型步骤、消耗了多少 token、调用了哪些工具和子智能体,以及最终是完成、失败还是被取消。

借助 SigNoz 中的完整 eve 可观测性,你可以逐轮追踪整个对话、按智能体或模型统计 token 消耗、发现智能体悄悄重试掩盖的工具失败,并对模型重试次数耗尽后仍失败的轮次设置告警。

前置条件

  • 一个 SigNoz Cloud 账号和对应的 ingestion key
  • Node.js 24 或更高版本
  • 一个 eve 项目,可通过 npx eve@latest init my-agent 创建
  • 在 eve 终端界面中已配置好模型凭证,例如 OpenAI API key

使用 OpenTelemetry 监控 Eve

eve 启动时会加载 agent/instrumentation/ 目录下的所有文件。只要某个文件导出了 otelIntegration(),就会添加一个 OpenTelemetry 输出目标,因此只需一个文件就能把追踪数据发送到 SigNoz。

第一步:从 @vercel/otel 安装 OTLP exporter。

Copy
npm install @vercel/otel

第二步:在项目根目录的 .env.local 中添加 SigNoz 配置,eve dev 会自动加载该文件。

Copy
OTEL_SERVICE_NAME=<service_name>
SIGNOZ_OTLP_ENDPOINT=https://ingest.<region>.signoz.cloud:443
SIGNOZ_INGESTION_KEY=<your-ingestion-key>

确认以下取值:

  • <service_name>:智能体在 SigNoz 中显示的名称,例如 support-agent。
  • <region>:你的 SigNoz Cloud 区域。
  • <your-ingestion-key>:你的 SigNoz ingestion key。

第 3 步:创建 agent/instrumentation/signoz.ts。

Copy
import { OTLPHttpProtoTraceExporter } from "@vercel/otel";
import { otelIntegration } from "eve/instrumentation/otel";
 
const AGENT_SPANS = /^(invoke_agent|agent\.step|agent\.action|chat|execute_tool)( |$)/;
 
export default otelIntegration({
  // 保留 eve 的 agent spans,丢弃 durable-workflow runtime spans。
  exportPolicy: { span: ({ name }) => ({ emit: AGENT_SPANS.test(name) }) },
  traceExporter: new OTLPHttpProtoTraceExporter({
    url: `${process.env.SIGNOZ_OTLP_ENDPOINT}/v1/traces`,
    headers: { "signoz-ingestion-key": process.env.SIGNOZ_INGESTION_KEY! },
  }),
});
为什么要过滤 spans?

eve 在每个回合中运行于 durable workflow runtime,会生成自己的 workflow.*、step.* 和 queue.* spans,其中许多还是独立的 traces。它们占单回合总 spans 的 97% 左右,但对理解 agent 本身毫无帮助。exportPolicy 保留 5 种 agent span 类型,可将一次简单的 tool-calling 回合产生的 spans 数量从近 200 个降至 10 个以内。如果需要调试 workflow runtime 本身,可移除此过滤。

第 4 步:启动终端 UI 并发送一条消息。

Copy
npm run dev

每个回合结束后即导出。数据在 SigNoz 中显示最多需 30 秒。

按环境过滤?

eve 不设置 deployment.environment,而仪表盘模板的环境选择器正依赖该字段。在 agent/instrumentation/otel.ts 中添加它即可:

Copy
import { otel } from "eve/instrumentation/otel";
 
export default otel({
  resource: { "deployment.environment": process.env.VERCEL_ENV ?? "development" },
});
使用自建 SigNoz?

大部分步骤相同。要适配此指南,请更新 endpoint 并移除 ingestion key header,参考 Cloud to Self-Hosted 文档。

在 SigNoz 中查看 Eve Traces

打开 Traces 浏览器,并按 service.name 进行筛选。每一轮对话(turn)都会显示为一个 invoke_agent <agent> span,其中包含其 agent.step、chat、agent.action 以及 execute_tool span。

eve agent spans in the SigNoz Traces explorer
来自 eve agent 的对话轮次、模型步骤、模型调用及工具 span

点击一个 invoke_agent span 即可查看该轮对话。瀑布图展示了首个模型步骤请求工具、工具执行以及第二个步骤写入答案的过程。选中一个 chat span,即可在右侧查看模型、token 计数及会话 ID。

Detailed view of an eve turn in SigNoz
单轮对话:包含两个模型步骤和一次工具调用

每轮对话生成的 span 树结构如下:

Copy
invoke_agent <agent>          每轮对话对应一条 trace,携带 agent.turn.outcome
└─ agent.step                 每个模型步骤对应一个
   ├─ chat <model>            携带 gen_ai.request.model 和 gen_ai.usage.*
   └─ agent.action            每个工具或子 agent 调用对应一个
      └─ execute_tool <tool>

编写自定义查询时,有几个定位细节需要注意:

  • Token 信息出现在三个位置。 invoke_agent、agent.step 和 chat span 都携带相同的用量总计。统计总量时,请对 chat span 上的 gen_ai.usage.* 求和;仅在按 agent 细分时使用 invoke_agent。
  • 从 agent.turn.outcome 读取对话轮次结果。 当用户按下 Escape 键时,invoke_agent span 保持未设置状态,其 agent.turn.outcome 为 cancelled,而其子 span 则被标记为错误,错误类型为 TurnCancelledError。因此,使用 has_error 过滤器会将取消操作计为失败。
  • 工具错误归工具,不归回合。工具抛出异常时,它的 execute_tool 和 agent.action span 会被标记为错误,但模型可以恢复并完成该回合。而模型调用在重试后仍失败,则会导致整个回合失败。
  • Subagent 是独立的 trace。每个 subagent 回合都是独立的 invoke_agent trace,与其调用者关联并共享调用者的 gen_ai.conversation.id。它的 token 不会计入调用者的回合。
  • Provider 执行的工具没有工具 span。由模型 provider 自行运行的工具(如 OpenAI web search)只会显示为 agent.action span,没有 execute_tool 子 span。

记录 prompt 和 completion

eve 在 eve dev 环境下默认会在 span 上记录 prompt、completion 和工具参数;在生产环境中,仅当频道的受众为公开时才会记录。内容存放在 gen_ai.input.messages 和 gen_ai.output.messages 上,每个 chat span 都会重复完整的对话历史。

如需停止记录内容,可在 agent/instrumentation/otel.ts 中设置 tracePolicy。span、耗时和 token 计数仍会正常导出。

Copy
import { otel } from "eve/instrumentation/otel";
 
export default otel({
  tracePolicy: () => ({ emit: true, recordInputs: false, recordOutputs: false }),
});

该策略适用于所有 OpenTelemetry 目标端,不只是 SigNoz。如果你还设置了 deployment.environment,请把 resource 和 tracePolicy 放在同一个 otel() 调用中,因为 eve 只允许一个。

Eve 可观测性仪表盘

SigNoz 为 eve 提供了预置仪表盘,涵盖回合、对话、按模型和 agent 划分的 token 用量、延迟、工具、subagent、回合结果和错误等信息。面板说明和导入链接见 Eve dashboard 文档。

SigNoz 中的 Eve 仪表盘
Eve 仪表盘模板

Eve 可观测性问题排查

SigNoz 收不到 span

确认文件位于 agent/instrumentation/ 目录下,且已安装 @vercel/otel。与标准的环境变量 OTEL_EXPORTER_OTLP_ENDPOINT 不同,@vercel/otel 导出器需要完整的信号 URL,因此 url 必须以 /v1/traces 结尾。如果启动代理时使用的不是 eve dev,需自行加载 .env.local 文件。

每轮对话均报 "fetch failed" 或 "Lost the connection to the running turn" 错误

通常是因为之前的 eve dev 进程仍在运行,常见于终端关闭时未退出 UI 的情况。请停止所有 eve dev 进程并重新启动。注意,如果在状态行仍显示 "Starting agent…" 时发送消息,也会导致相同故障,因此需等待状态清除后再操作。

每轮产生数百个 span

这通常是因为缺失第 3 步中的 exportPolicy,导致 workflow 运行时 span 也被导出。请添加该策略,以便仅保留 agent span。

打包器警告 @vercel/otel 中包含 eval

在 agent 构建过程中,终端 UI 的 stderr 面板会显示 @vercel/otel 内部直接使用了 eval 的警告。该警告不影响数据导出。

Token 总量看似比供应商账单高出三倍

这是因为查询对 invoke_agent、agent.step 和 chat 三类 span 的用量进行了累加。请过滤条件设为 gen_ai.operation.name = 'chat' 以获取准确的总量。

使用 /model 切换模型后轮次失败

/model 命令会将 agent/agent.ts 改写为 AI Gateway 模型字符串,从而通过 Vercel AI Gateway 路由调用。若未配置 Gateway 凭证,每次模型调用在重试三次后均会失败。请在 UI 中连接 Vercel 账号或 AI Gateway 密钥,或在 agent/agent.ts 中恢复供应商辅助函数,例如 openai("gpt-5.6-sol")。

Span 中缺少成本属性

Eve 仅对通过 Vercel AI Gateway 提供的调用报告成本。通过 openai() 等供应商辅助函数发起的调用只包含 token 数量而不含成本,因此需根据 token 数量和模型费率自行计算成本。

配置 OpenTelemetry Collector(可选)

评论 (0)