使用 OpenTelemetry Collector 过滤并精简 AI 智能体遥测数据

使用 OpenTelemetry Collector 过滤并精简 AI 智能体遥测数据

💡 原文英文,约2000词,阅读约需8分钟。
📝

内容提要

文章介绍如何用 OpenTelemetry Collector 优化 Claude Code 的遥测数据。默认遥测包含大量提示词、文件内容和工具参数,存储成本高且难以分析。作者将数据分流为原始与优化两条管道进行对比:日志删除冗余字段并哈希 ID,指标删除高基数属性并合并会话,追踪删除成功工具事件、截断内容而不采样。结果日志和追踪体积约减半,指标基数从 300 降至 12,且关键问题仍可回答。

🔎

延伸解读

先明确要回答的问题,再决定删什么

文章的核心思路不是盲目减少采集,而是先列出六个必须回答的问题:成本、令牌、工具失败、编辑拒绝、延迟和错误。每个答案都对应计数器或短属性,不需要提示词、文件正文或差异内容。这提醒读者,优化遥测前应先定义查询和仪表盘需求,否则容易删掉真正有用的字段,或保留大量无人读取的存储负担。

体积主要来自工具内容和重复存储

默认开启内容标志后,一次简单任务就产生181条记录和289 KB JSON。工具输出会同时进入追踪的 span 事件和日志的 tool_parameters,40 KB 文件被存两次;指标则因每个数据点携带会话、用户和账户标识,25个会话就让8个指标膨胀到300条时间序列。可见优化重点应放在删除重复内容、截断大字段和移除高基数属性上。

指标优化需先合并会话再转换累积值

指标的问题不是字节而是基数。删除 session.id 等六个属性后,300条序列降到12条。但 Claude Code 导出的是 delta 时序,Prometheus 需要 cumulative,因此必须先按两秒窗口批处理、统一时间戳并求和,再执行 delta_to_cumulative。文章还提醒,该方案要求单个 Collector 看到所有会话,放在负载均衡后需部署在单一网关。

追踪用截断替代采样,保留可追溯性

追踪是最大数据流,但作者没有直接采样,而是删除成功工具的子事件、删除与 gen_ai.* 重复的属性,并把内容、输出和差异截断到512字符,同时标记 content_truncated_by_pipeline。这样每次运行仍可被调出,体积约减半。文章也指出采样会牺牲按具体运行排查的能力,且长时交互可能让尾部采样在失败发生前就做出决定。

❓

Q&A

Claude Code 默认遥测数据为什么存储成本高且难以分析?

默认遥测包含大量提示词、文件内容和工具参数,例如开启 OTEL_LOG_TOOL_CONTENT 后,一次 Read 工具调用会把整个文件内容作为 span 事件存储,40 KB 文件就产生 40 KB 事件;日志中的 tool_result 和 tool_decision 事件也携带完整工具参数,同样内容被存储两次。指标则携带 session.id、user.id、user.email 等高基数属性,每个新会话都创建永不消失的时间序列,25 个会话就产生 300 条序列。这些数据对单次调试有用,但大规模运行时存储昂贵且难以分析。

如何用 OpenTelemetry Collector 精简 Claude Code 的日志数据?

在优化管道中依次使用三个处理器:1) filter/drop_api_request 丢弃整个 api_request 事件(约占日志四分之一);2) transform/logs_delete_fields 删除 prompt、response、tool_parameters、workspace.host_paths、user.email、terminal.type 六个属性,保留 prompt_length 和 response_length 以观察大小趋势;3) transform/logs_hash_and_trim 对 session.id 和 user.id 做 SHA256 哈希并截取前 16 个十六进制字符,将 error 字段截断至 256 字符。处理后日志字节数大约减半。

OpenTelemetry Collector 如何降低 Claude Code 指标的基数?

通过删除每个数据点上的六个高基数属性(session.id、user.account_uuid、user.account_id、user.id、user.email、terminal.type),使 300 条序列降至 12 条。由于删除了 session.id,需要先合并会话:用 batch/metrics_window 每 2 秒收集一批,groupbyattrs/compact 将同名指标归入同一资源,transform/metrics_merge_sessions 给所有点统一时间戳并按属性聚合求和,最后用 delta_to_cumulative 将 delta 时序转换为 Prometheus 所需的 cumulative 时序。优化后总量与原始数据误差在 0.5% 以内。

为什么文章建议对追踪数据做截断而不是采样?

采样会牺牲追踪的核心用途——调出用户询问的特定运行记录。而且智能体交互可能持续数分钟,tail_sampling 要等 decision_wait 后才做决定,若工具在第三分钟失败,数据到达时已过决策点。因此作者选择用过滤器丢弃成功的 tool.execution 事件(父 span 已含 tool_name、duration_ms、result_tokens),并用 transform 删除重复属性、哈希身份标识、将 span 事件中的 content、output、diff 截断至 512 字符并标记 content_truncated_by_pipeline。这样每个 span 都保留,追踪字节数约减半且不采样。

如何验证优化管道没有丢失关键可观测性信息?

文章采用双管道对比法:同一个 OTLP 接收器将数据分发给原始管道和优化管道,原始管道仅含 batch 处理器作为对照组,两者输出到同一个 Grafana LGTM 实例。通过开启 Collector 详细自监控指标(level: detailed),并用 resource 和 transform 处理器给两条路径打上 service.name 和 pipeline 标签,在仪表板上并排展示基数、每分钟字节数和记录数。结果显示基数从 300 降至 12,日志和追踪字节数约减半,且优化流仍能回答成本、令牌、工具失败、编辑拒绝、延迟和错误六类问题。

精简后的遥测数据还能回答哪些关键问题?

文章列出六个核心问题及对应数据:每个模型的成本(claude_code.cost.usage)、每会话令牌数及缓存量(claude_code.token.usage 按类型)、哪些工具失败及频率(tool_result 事件的 success)、用户是否拒绝智能体编辑(tool_decision 事件)、延迟位置(llm_request span 的 ttft_ms)、出了什么错(api_error 事件的 error_class)。这些答案都是计数器或短属性,不需要提示词、文件正文或 diff。优化后仅 12 条序列即可填充所有面板并回答全部问题。

🏷️

标签

➡️

继续阅读