接入遥测,拆解 Claude Code 用量成本
文章介绍通过 OpenTelemetry 将 Claude Code 的用量和工具事件导出到自有观测系统,并按模型、子代理、技能等维度分析消耗。提示词等敏感内容默认不导出,成本数值属于本地估算,不能直接视为账单。
AI 深度解读
Claude Code 能统计的不只是用了多少 token,还能把一次指令的模型调用、工具执行、权限等待和估算成本串起来。原文的核心建议是:个人先验证 OpenTelemetry 导出,再通过团队托管配置统一接入自己的监控系统。
对程序员来说,价值在于回答更具体的问题:慢在模型还是权限确认?费用来自主会话、subagent,还是某个 MCP server?但这些数字有明确边界,尤其不能把本地成本估算当成账单。
/usage 能看个人,团队需要统一的数据入口
/usage 根据本机的会话历史计算统计,不包含其他设备或 claude.ai 上的使用。一个人临时查用量够用,团队要比较不同周、仓库和工作流,就缺少统一入口。
OpenTelemetry 把指标和事件送进集中式监控系统。原文转述官方文档称,它适用于各种部署方式,也是将每位用户的 token 和成本指标近实时送进自有系统的唯一选项。
其他入口各有适用范围:Teams、Enterprise 有支出报告和分析面板,API 客户有 Console 和 Claude Code Analytics API;Amazon Bedrock、Google Cloud's Agent Platform、Microsoft Foundry 则有各自的云账单控制台。云平台场景要得到逐用户数据,原文指出仍需 OpenTelemetry 或 LLM gateway。
先划清一个边界:
遥测里的美元数字适合比较工作流,不适合直接结算。
Claude Code 根据 token 数量和标价在本地估算成本。Pro、Max 的用量包含在订阅里,显示的金额不是额外账单;API 用户也应以 Console usage 页面为准。合同价格需要管理员通过 modelPricing 托管设置配置,要求 Claude Code v2.1.242 或更高版本,而且只改变报告口径,不改变收费。
先跑通导出,再把配置交给团队管理
启用遥测需要在启动 Claude Code 前设置环境变量。下面这段同时导出 metrics 和 logs,并指定接收端:
export CLAUDE_CODE_ENABLE_TELEMETRY=1 # 必填
export OTEL_METRICS_EXPORTER=otlp # otlp, prometheus, console, none
export OTEL_LOGS_EXPORTER=otlp # otlp, console, none
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc # grpc, http/json, http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer your-token"
最容易漏的是 OTEL_EXPORTER_OTLP_PROTOCOL:OTLP 没有默认协议,每个启用的 exporter 都要通过通用变量或对应信号的变量明确设置。
正式接 collector 前,可以先每秒把指标打印到终端,排除接收端的干扰:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=console
export OTEL_METRIC_EXPORT_INTERVAL=1000
这里的 1000 单位是毫秒。默认 metrics 每 60 秒导出一次,由 OTEL_METRIC_EXPORT_INTERVAL 控制;logs 默认每 5 秒导出一次,由 OTEL_LOGS_EXPORT_INTERVAL 控制。
验证 metrics 看会话启动时的 claude_code.session.count;只接 logs 时,提交一次提示词后找 claude_code.user_prompt。没有数据就用 claude --debug-file <path> 启动,搜索 [3P telemetry]。[Anthropic telemetry] 属于 Anthropic 自身的运行遥测,不能据此判断自建链路出错。另一种选择是设置 OTEL_METRICS_EXPORTER=prometheus,抓取 http://localhost:9464/metrics。
metrics 和 logs 可以分开投递。例如,分别设置 OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf、OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://metrics.example.com:4318,以及 OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=grpc、OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://logs.example.com:4317。专用配置覆盖通用配置,但专用 headers 会与 OTEL_EXPORTER_OTLP_HEADERS 合并。指标默认采用 delta;后端要求累计值时,设置 OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=cumulative。
团队部署应把变量放进 managed settings 的 env。仓库里的 .claude/settings.json、.claude/settings.local.json 不能开启遥测、改目的地或开启内容采集;但在更高优先级配置未指定时,仍可用 none 关闭某类信号。
托管配置还有两层约束:
- 设置通用 endpoint 会移除开发者设置的专用 endpoints,protocol 同理;设置 headers 或客户端密钥、证书,还会清除对应专用配置及开发者 endpoints。
- 这些规则不会自动锁住
OTEL_METRICS_EXPORTER、OTEL_LOGS_EXPORTER、OTEL_TRACES_EXPORTER。要锁住选择器,也得写入托管配置,且要求 v2.1.223 或更高版本。
另外,OTEL_* 不会传给 Bash 工具、hooks、MCP servers 或语言服务器,脚本不会直接继承 collector 凭据。
真正有用的是,把成本、工具和等待串起来
成本与 token 指标可按 model、query_source、speed、effort 拆分;query_source 区分 main、subagent、auxiliary。还可以关联 agent.name、skill.name、plugin.name、mcp_server.name、mcp_tool.name。
不过,agent、skill、plugin、MCP 名称默认会被替换为 custom 或 third-party。想看到真实名称,需要 OTEL_LOG_TOOL_DETAILS=1,同时评估命令等工具细节进入日志的影响。
logs 中的事件统一带 claude_code. 前缀。api_request 记录模型、cost_usd、duration_ms、token 数和 request_id;api_error 提供 error、status_code、attempt;tool_result 记录工具、成功状态、耗时和决策来源;tool_decision 则记录接受或拒绝、来源及权限模式。
通过 prompt.id 可以关联同一提示词下的事件。排序要先用 event.timestamp,因为 event.sequence 只是进程内计数器。
要进一步观察调用链,需要同时开启 CLAUDE_CODE_ENABLE_TELEMETRY=1、CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1,并选择 OTEL_TRACES_EXPORTER。每个提示词以 claude_code.interaction 为根 span,下接 claude_code.llm_request 和 claude_code.tool;工具 span 里的 blocked_on_user、execution 能区分等待确认与实际执行。claude_code.hook 还要求 ENABLE_BETA_TRACING_DETAILED=1、BETA_TRACING_ENDPOINT,交互式 CLI 会话另需组织 allowlisting。
原文建议先建四类面板:token 类型趋势、各 agent 或工具的成本、权限拒绝及等待时间、按状态码统计的 API 错误。比如 cacheCreation 高、cacheRead 低,可能说明上下文反复重建,但不能仅凭这个比例就断定原因。
隐私也要单独检查。提示词、工具细节、原始 API body 默认不采集,各有独立开关;原文在这一段缺失了具体开关列表,不能据此补全配置。user_prompt 和 assistant_response 默认仅记录长度,内容属性默认截断于 60 KB,由 CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH 控制。
标准属性还包括 session.id、user.account_uuid、匿名随机的 user.id 和 user.email。没有正文不等于没有个人信息。
指标属性越多,时间序列数量越大。只按团队或模型看趋势时,可设置 OTEL_METRICS_INCLUDE_SESSION_ID=false,避免每个会话产生新序列。自定义维度用 OTEL_RESOURCE_ATTRIBUTES,例如 department=engineering,team.id=platform;值不能包含空格,加引号也不能转义。
我的判断
这套做法最有说服力的地方,是把优化对象具体化了:一次任务到底花在哪里、卡在哪里,可以留下可比较的记录。仓库不能偷偷改遥测目的地,也让团队统一配置有了明确边界。
但原文没有给出接入前后的降本或提速数据。四类面板是排查建议,尚不能视作验证过的优化方案。换小模型、降低 effort 后,除了比较 claude_code.cost.usage,还要检查任务完成质量和返工,否则只证明了单次调用更便宜。
个人偶尔查用量,/usage 的维护成本更低;团队仅核对总支出,也可能已有足够的账单入口。需要跨用户、跨工具分析时,自建遥测的价值才更明确。
原文最后介绍的 Atlas 是独立产品,使用用户自己的 Pro 或 Max 会话,并发会更快消耗套餐限额。其每日预算在 50%、80% 提醒,100% 暂停,但当时尚不支持 OpenTelemetry 导出。未来内置导出的说法属于产品计划,不能当作已有能力。
能拿来做什么
- 先在一台开发机上用 console exporter 验证
claude_code.session.count,确认有数据后再接团队 collector,减少同时排查多个环节的成本。 - 针对一类固定的日常编码任务,比较模型或
effort调整前后的估算成本、耗时和完成质量,避免仅凭 token 数决定工作流。 - 排查 AI 编程卡顿时,同时看
api_error、工具耗时与blocked_on_user,据此区分服务错误、执行缓慢和权限等待。 - 团队先保留指标与事件元数据,再按需要开启工具细节;如果只关心团队趋势,就移除 metrics 中的 session ID,并检查 collector 是否保留邮箱。