VolcengineVolcengine ADK

链路追踪

Tracing(链路追踪)对智能体执行过程进行全链路记录,是企业级智能体应用实现可观测性的核心。它把一次请求的完整流程——用户输入、模型推理、工具调用、记忆与知识库读写、响应生成——转化为可分析、可追溯的结构化数据,为调试、监控和优化提供依据。

在 VeADK 中开启观测

为智能体配置一个 OpentelemetryTracer,并指定一个或多个 Exporter,即可开启全链路观测。下例使用 APMPlus Exporter:

examples/tracing/tracing_exporter.py
import asyncio
from veadk import Agent, Runner
from veadk.tracing.telemetry.exporters.apmplus_exporter import APMPlusExporter
from veadk.tracing.telemetry.opentelemetry_tracer import OpentelemetryTracer

# 初始化 Tracing Exporter
exporters = [APMPlusExporter()]
tracer = OpentelemetryTracer(exporters=exporters)

# 定义智能体并挂载 tracer
agent = Agent(tracers=[tracer])

runner = Runner(agent=agent)
response = asyncio.run(runner.run(messages="hi!"))
print(response)

可通过环境变量配置 Exporter:

  • OBSERVABILITY_OPENTELEMETRY_APMPLUS_API_KEY:APM 服务的 API Key
  • OBSERVABILITY_OPENTELEMETRY_APMPLUS_ENDPOINT:APM 服务的 Endpoint,例如 http://apmplus-cn-beijing.volces.com:4317
  • OBSERVABILITY_OPENTELEMETRY_APMPLUS_SERVICE_NAME:APM 的 Service Name,例如 python_coder_agent - OBSERVABILITY_OPENTELEMETRY_TRACE_CONTENT:是否采集 Agent、LLM 与工具输入输出内容,默认 true`

或在 config.yaml 中定义:

config.yaml
observability:
  opentelemetry        trace_content: true
    apmplus:
      endpoint: ...
      api_key: ...
      service_name: ...

开启后,日志中会打印出相关 Tracing 数据的 ID:

TraceID 示意

针对不同平台的完整接入方式,参见在火山引擎观测。

限制本地缓存

以下配置随本次修复提供,已发布的 1.1.14 及更早版本不支持这些配置

OpentelemetryTracer 默认保留最近的 1024 个 Span,估算数据总量最多为 16 MiB。达到任一上限时会淘汰最早的 Span;单个 Span 超过字节上限时不写入本地缓存,仍按原有配置交给云端 Exporter

在启动应用前,可通过以下环境变量调整本地缓存:

环境变量类型默认值说明
OBSERVABILITY_OPENTELEMETRY_INMEMORY_ENABLED布尔值true是否保留本地 Span 历史
OBSERVABILITY_OPENTELEMETRY_INMEMORY_MAX_SPANS非负整数1024最多保留的 Span 数量,0 表示不保留
OBSERVABILITY_OPENTELEMETRY_INMEMORY_MAX_BYTES非负整数16777216估算数据量上限,单位为字节,0 表示不保留

仅需云端观测时,在启动应用的终端设置:

export OBSERVABILITY_OPENTELEMETRY_INMEMORY_ENABLED=false

关闭本地缓存后,Span 标注、日志中的 Trace ID 和已配置的云端上报保持可用,tracer.dump() 写入空数组。启用缓存时,dump() 只包含仍保留的会话历史;用于关联会话的 Span 被淘汰后,对应链路也可能不再出现在本地导出中,完整历史应在云端观测平台查询

同一个 TracerProvider 下的 tracer 共享上述额度。配置在首次创建缓存时生效,修改后需重启应用或创建新的 Provider;字节数是缓存数据的估算值,不代表整个进程的内存上限

Tracing 的价值

引入 Tracing 后,你可以:

  • 调试与定位问题:快速定位逻辑错误、工具调用失败或模型输出异常发生的环节;
  • 性能分析:通过各模块的执行耗时发现瓶颈,优化模型调用与工具执行策略;
  • 审计与合规:保留完整的请求、响应与决策记录;
  • 多 Agent 协调:分析多 Agent 协作中各 Agent 的调用关系与数据流向。

Tracing 数据结构

Tracing 数据由一系列 Span 组成,每个 Span 记录一次操作(如调用模型、执行工具)的名称、ID、起止时间与属性。下面是单个工具调用 Span 的示例:

tracing.json
{
  "name": "execute_tool get_city_weather",
  "span_id": 15420762184471404328,
  "trace_id": 195590910357197178730434145750344919939,
  "start_time": 1762770336065962000,
  "end_time": 1762770336066380000,
  "attributes": {
    "gen_ai.operation.name": "execute_tool",
    "gen_ai.tool.name": "get_city_weather",
    "gen_ai.tool.input": "{\"name\": \"get_city_weather\"}",
    "gen_ai.tool.output": "{\"response\": {\"result\": \"Sunny, 25°C\"}}",
    "cozeloop.input": "{\"name\": \"get_city_weather\"}",
    "cozeloop.output": "{\"response\": {\"result\": \"Sunny, 25°C\"}}"
  },
  "parent_span_id": 18301436667977577407
}

各属性字段的含义见埋点字段说明。

在多 Agent 场景中,多个 Span 通过 parent_span_id 串联,展现 coding_agent 调度 python_coder 的完整链路:

tracing.json
[
  {
    "name": "execute_tool transfer_to_agent",
    "span_id": 8839983747734433620,
    "trace_id": 161011438572144016825706884868588853689,
    "attributes": {
      "agent.name": "coding_agent",
      "gen_ai.operation.name": "execute_tool",
      "gen_ai.tool.name": "transfer_to_agent"
    },
    "parent_span_id": 5680387922600458423
  },
  {
    "name": "call_llm",
    "span_id": 6376035117066938110,
    "trace_id": 161011438572144016825706884868588853689,
    "attributes": {
      "agent.name": "python_coder",
      "gen_ai.request.model": "openai/doubao-seed-1-8-251228",
      "gen_ai.request.type": "chat",
      "gen_ai.span.kind": "llm",
      "gen_ai.prompt.0.role": "user",
      "gen_ai.prompt.0.content": "使用 Python 帮我写一段快速排序的代码。"
    },
    "parent_span_id": 11028930176666491606
  },
  {
    "name": "invoke_agent python_coder",
    "span_id": 11028930176666491606,
    "trace_id": 161011438572144016825706884868588853689,
    "attributes": {
      "gen_ai.span.kind": "agent",
      "gen_ai.operation.name": "invoke_agent",
      "gen_ai.agent.description": "擅长使用 Python 编程语言来解决问题。",
      "gen_ai.system": "openai",
      "agent.name": "python_coder"
    },
    "parent_span_id": 5680387922600458423
  },
  {
    "name": "invoke_agent coding_agent",
    "span_id": 987150150265236585,
    "trace_id": 161011438572144016825706884868588853689,
    "attributes": {
      "gen_ai.span.kind": "agent",
      "gen_ai.operation.name": "invoke_agent",
      "gen_ai.agent.description": "可以调用适合的智能体来解决用户问题。",
      "gen_ai.system": "openai",
      "agent.name": "coding_agent"
    },
    "parent_span_id": 11431457420615823859
  },
  {
    "name": "invocation",
    "span_id": 11431457420615823859,
    "trace_id": 161011438572144016825706884868588853689,
    "attributes": {
      "gen_ai.operation.name": "chain",
      "gen_ai.span.kind": "workflow",
      "gen_ai.system": "openai",
      "agent.name": "python_coder"
    },
    "parent_span_id": null
  }
]

与 OpenTelemetry 的兼容性

VeADK 的字段命名遵循 OpenTelemetry 生成式 AI 规范,你可以直接将 Tracing 数据导入到 OpenTelemetry 兼容的系统中进行分析和可视化。

请求、模型与首 Token 时间戳

启用 OpenTelemetry Tracing 后,VeADK 默认 LiteLLM 和 Ark Responses 适配器会在模型 Span 上添加以下扩展属性。时间戳统一采用 UTC Unix 纳秒。

属性含义
veadk.request.start_time_unix_nsVeADK AgentKit/Harness 应用的 HTTP ASGI 入口,或直接调用 VeADK Runner 的执行入口。
veadk.request.start_sourcehttp 或 runner;继承的 HTTP 时间戳优先。
veadk.model.start_time_unix_ns一次适配器 SDK 请求的开始,不是服务端开始推理。
veadk.model.streaming实际模型 SDK 请求模式,与 HTTP SSE 传输独立。
veadk.model.first_token_time_unix_ns收到首个非空生成内容增量的时间。
veadk.model.first_token_typetext、reasoning 或 tool_call。
veadk.model.first_token_statusobserved、non_streaming、no_output 或 unsupported。

首 Token 采集排除角色/id/签名元数据、空增量、usage、心跳和仅完成时返回的聚合内容。不依赖 token usage 或内容采集。一个 chunk 可含多个 token,因此这里表示 SDK 侧观测到首输出的时间。非流式调用没有首 Token 时间戳,不能用响应完成时间替代。

每次 SDK 请求建立 model_request 子 Span,所属模型 Span 同时记录最近一次尝试的字段。VeADK 发起的重试和 fallback 分别记录尝试;LiteLLM/Provider 内部重试计入所观测的 SDK 请求(veadk.model.request_scope=sdk_request)。不支持的外部/自定义引擎明确标记,不用 invocation Span 起点替代模型开始。未使用 VeADK HTTP 工厂的应用需要安装请求计时中间件或使用 VeADK Runner,才能建立请求时间戳。客户端渲染计时和 TTFT/TPOT 直方图上报属于独立能力。

本页导航