Claude Code 费用追踪工具对比:日志、仪表板与 OTel
对比本地 JSONL 日志解析器、Anthropic 内置使用量页面和 OpenTelemetry 追踪栈,说明三者读取的数据、统计差异及各自无法回答的问题。
Claude Code 费用追踪器实际读取什么
每个 Claude Code 费用追踪器都会读取三类数据源之一,而数据源决定了它能回答哪些问题。日志解析器读取您本地磁盘上的会话记录文件。仪表板读取 Anthropic 为您的账户或组织保留的使用记录。指标后端读取您启用后由 Claude Code 发出的 OpenTelemetry (OTel) 数据流。这三者可以同时正确,但结果仍可能不一致,因为它们统计的是不同内容。
本指南不再解释 token。Claude Code 如何统计 token 使用量介绍了输入、输出、缓存写入和缓存读取;只有先弄清这些内容,仪表板中的数据才有意义。本文只讨论一个更具体的问题:每类工具能看到什么,以及永远看不到什么。
为什么同一天出现了 3 个 Claude Code 使用成本跟踪工具
同一天发布了 3 个独立的 Claude Code 使用成本跟踪工具。它们并不是同一工具的 3 个版本,这一点很有价值。其中一个解析本地会话文件。一个封装账户使用情况页面。另一个是由您自行运行的托管式追踪后端。
它们同时出现,是因为 agent 会话的成本不再直观。聊天的成本大致可以从屏幕上看到。agent 会读取 20 个文件、运行测试套件,并在每一轮重新发送完整对话,因此账单由您从未输入的上下文驱动。订阅模式下甚至没有具体的金额,只有一个使用量进度条,而且某些日期的消耗速度会更快。这 3 种工具分别弥补了这一缺口的不同部分。
方案 1:使用本地日志解析器查看今天的消耗
Claude Code 会将每段对话以 JSON Lines(JSONL)格式存储在 ~/.claude/projects/<project>/<session-id>.jsonl,其中 <project> 是您的工作目录路径,非字母数字字符会替换为 -。该文件中的每次 assistant 交互都包含本次请求的 token 数量。日志解析器会汇总这些数量并计算价格。
ccusage 是大多数人最终选择的工具。它无需安装:
npx ccusage@latest daily
npx ccusage@latest daily --breakdown
npx ccusage@latest blocks
npx ccusage@latest session --jsondaily 按日期汇总。--breakdown 按模型拆分每一行,您可以借此发现某个 Opus 下午的消耗占了一周的大部分。blocks 按订阅重置的五小时窗口分组。session 按对话汇总,--instances 按项目分组,因此您可以查看哪个代码仓库的成本较高。添加 --since 和 --until 可限定日期范围,并运行 npx ccusage@latest daily --help 以查看您的版本所需的日期格式。截至 August 2026,它还可以读取其他 agent CLI 的数据,包括 Codex 和 OpenCode;如果您要比较这些工具,这一点很重要。
价格来自模型价格表。该工具提供三种成本模式。--mode auto 会在文件中存在 costUSD 值时使用 Claude Code 写入的该值;如果不存在,则根据 token 数量计算。--mode calculate 始终根据 token 数量计算,并忽略已记录的成本。--mode display 只显示已记录的成本;对于没有记录成本的行,会输出 $0.00。如果某个总数看起来不正确,请先使用 calculate 运行同一报表,再使用 display 运行。如果两者差异很大,说明大多数条目没有记录成本,因此您看到的全部都是估算值。
相同的数据也可以用于提示信息。ccusage statusline 会输出一行简要信息,供 Claude Code 状态栏使用;您可以像配置其他状态栏命令一样,将其接入 ~/.claude/settings.json。请参阅构建 Claude Code 状态栏,了解设置代码块及其接收的字段。
日志解析器无法看到没有发生在本机上的活动。另一台笔记本电脑、claude.ai 中的会话以及团队成员的工作,都只保存在对应设备的磁盘上。旧数据也可能已经缺失,因为在 cleanupPeriodDays 设置下,transcript 默认会在 30 天后清理。因此,除非您提前归档,否则上个季度的数据已经不存在。
还有一个结构性风险。Anthropic 的文档说明,条目格式属于 Claude Code 内部格式,并且会随版本变化。因此,直接解析这些文件的脚本可能在任何一次发布后失效。所有此类工具都存在这一问题。这也是手写 jq JSONL 单行命令并不如看起来可靠的原因:维护中的解析器会跟踪格式变化,而字段重命名后,您的单行命令可能会输出一个看似确定、实际错误的数字。
最后,订阅用户需要注意美元金额的含义。Pro 或 Max 并不会按 token 计费,因此该数字表示按 API 标准价格计算时,您的 token 原本会产生的成本。它反映使用量的大小,但不是您的账单。如果您真正想确认应该选择哪个套餐,这需要单独比较;请参阅API 计费与 Claude 订阅的对比。
方案 2:内置使用量页面会告诉您哪个模型消耗了预算
Claude Code 自带报告功能,但大多数人从未打开过。请在会话中运行 /usage。顶部的 Session 区块会按模型显示 token 数量和当前会话的美元金额。该金额根据 token 数量和标准标价在本地计算。它不反映折扣或促销价格,因此可能与您的账单不同。/clear 开始新对话时,总数会重置。
在 Pro、Max、Team 或 Enterprise 计划中,同一个页面还会显示您已使用的计划限额,并将近期使用量按技能、子代理、插件和各个 MCP 服务器归类为总量的百分比。对于占近期使用量 10% 或以上的行为,页面会予以标记,例如长上下文或缓存未命中。按 d 或 w 可在最近 24 小时和最近 7 天之间切换。这些数据为近似值,根据此设备上的本地会话历史计算,因此不会统计第二台设备的使用量。
当开发者数量超过 1 人时,数据会转移到帐户级别。API 组织可使用 Console usage 页面、Claude Code 控制面板,以及 Claude Code Analytics API。控制面板会按成员显示支出和已接受的代码行数;Analytics API 使用管理员密钥返回相同的每日用户级指标。Teams 和 Enterprise 计划可在管理控制台中查看支出报告并导出 CSV,报告每日更新;Enterprise 还提供 analytics API。您能看到哪些内容取决于每个开发者的登录方式,因此混合组织需要查看两份报告,再手动汇总。
用于估算预算时,Anthropic 成本文档截至 August 2026 发布的数据是:每位开发者每个活跃日平均接近 $13,每位开发者每月 $150 到 $250,且 90% 的用户每个活跃日低于 $30。请将其视为企业部署中的公开基准,而不是对您团队的预测。请先运行小范围试点并进行测量,再外推结果。
控制面板无法看到低于“日期”和“人员”两个粒度的详细信息。它们会告诉您 Opus 占据了 Tuesday 的大部分使用量,但不会告诉您是哪个提示、哪个代码仓库或哪个 CI 任务造成的。它们还存在延迟,因为组织级报告每日更新。因此,它们适合复盘,不适合用来捕获当天失控的代理。捕获失控代理需要限制,而不是报告;相关内容请参阅 在 VPS 上限制代理成本。
方案 3:自建 OpenTelemetry 堆栈,找出是哪个提示词导致性能回退
设置一个环境变量后,Claude Code 会发送 OpenTelemetry 指标和事件。这是唯一一种能将每个用户的 token 和成本数据近实时写入您控制的系统的方案。指标包括 claude_code.cost.usage(单位为 USD)、claude_code.token.usage(单位为 token)、claude_code.session.count 和 claude_code.active_time.total。
token 指标尤其有价值,因为它包含多个属性。每个数据点都包含 type,其值可能是 input、output、cacheRead 或 cacheCreation;还包含 model 和 query_source,其值可能是 main、subagent 或 auxiliary。此外,它还包含 agent.name、skill.name、mcp_server.name 和 mcp_tool.name。这些信息足以回答许多仪表板无法回答的问题:账单中有多少来自子代理,而不是您自己的交互;某个 MCP 服务器是否使输入 token 翻了一倍;有人编辑 CLAUDE.md 后,缓存读取是否大幅减少。缓存行为通常是意外情况的来源,提示词缓存何时能够收回成本解释了应如何分析这些数据。
这里需要纠正一个经常在相关讨论中出现的问题。Langfuse 是一个很好的自托管追踪后端,在 VPS 上运行 Langfuse 的方法见为代理追踪自托管 Langfuse。它的 OTLP 端点只接受追踪数据。Claude Code 导出的是指标和日志事件,而不是 span。因此,将 OTEL_EXPORTER_OTLP_ENDPOINT 指向 Langfuse 后,项目会保持为空,也不会产生任何有用的错误信息。对于您通过 API 自行构建的代理,Langfuse 是合适的工具,因为您自己的代码会为每个请求创建 span,并记录提示词、模型和成本。对于 Claude Code CLI,指标存储更合适。
在自己的 VPS 上设置 Claude Code 费用跟踪
只需两个服务:一个用于接收指标,另一个用于存储指标的 Prometheus。不要让这两个服务暴露在公网,因为开放的 OTLP 端口会接受任何发现该端口的人的写入请求。写入 /opt/ccmetrics/compose.yaml:
services:
collector:
image: otel/opentelemetry-collector-contrib:latest
command: ["--config=/etc/otel/config.yaml"]
volumes:
- ./collector.yaml:/etc/otel/config.yaml:ro
ports:
- "10.8.0.1:4318:4318"
restart: unless-stopped
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prom-data:/prometheus
ports:
- "127.0.0.1:9090:9090"
restart: unless-stopped
volumes:
prom-data:10.8.0.1 是服务器在 WireGuard 隧道中的地址,因此采集器只能从您的设备访问,其他来源无法访问。端口前的地址在这里很重要,因为 Docker 发布的端口不会受到 ufw 过滤:参见Docker 发布的端口为何会绕过 ufw。隧道本身的配置方法见在自己的 VPS 上配置 WireGuard VPN。
/opt/ccmetrics/collector.yaml:
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
processors:
batch:
exporters:
prometheus:
endpoint: 0.0.0.0:8889
service:
pipelines:
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheus]/opt/ccmetrics/prometheus.yml。8889 端口不会发布到主机,因为 Prometheus 会通过 Compose 网络中的服务名访问采集器:
global:
scrape_interval: 30s
scrape_configs:
- job_name: claude-code
static_configs:
- targets: ["collector:8889"]cd /opt/ccmetrics
docker compose up -d
docker compose logs collector采集器日志应以 Everything is ready. Begin running and processing data. 结尾。日志因配置错误而停止,表示 YAML 解析失败,容器会不断重启。
现在将 Claude Code 指向该采集器。在每台运行 Claude Code 的设备上,将以下内容添加到 ~/.claude/settings.json:
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_LOGS_EXPORTER": "none",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://10.8.0.1:4318",
"OTEL_METRIC_EXPORT_INTERVAL": "10000"
}
}启动一个会话,发送一条提示,等待导出间隔结束(此处为 10 秒,默认值为 60 秒),然后让 Prometheus 查询已收集的指标:
curl -s http://localhost:9090/api/v1/label/__name__/values | grep -o 'claude_code[a-z_]*'您应看到多个以 claude_code_ 开头的名称。导出器会将点替换为下划线,并追加单位,因此确切名称取决于采集器版本。结果为空表示没有数据到达。请检查协议和端口是否匹配,因为 http/protobuf 使用 4318,grpc 使用 4317,端口不匹配时会静默失败。运行 claude --debug,调试日志会报告 OTel 导出错误。
如果只有一台设备且不需要服务器,可以跳过上述所有步骤。设置 OTEL_METRICS_EXPORTER=prometheus 后,Claude Code 会直接在 http://localhost:9464/metrics 暴露抓取端点。当 prometheus 是唯一列出的导出器时,Claude Code 会从指标名称中省略 USD、tokens 和 s 单位,以确保抓取结果保持有效的 Prometheus 文本格式。
采用这种架构还涉及一项隐私决策。默认情况下,只有计数会离开设备,不会发送提示文本或工具输出。OTEL_LOG_USER_PROMPTS=1 和 OTEL_LOG_TOOL_CONTENT=1 会改变这一点,此时您的指标服务器中会保存源代码以及上下文中的其他内容。请谨慎启用这些选项,并先阅读避免将机密信息放入代理上下文。
跟踪脚本和 CI 运行的费用
非交互式运行最容易造成意外开支,因为没有人实时查看屏幕。使用 claude -p 和 --output-format json,可在运行结果的 payload 中报告本次运行的费用:
claude -p "summarise the failing tests" --output-format json | jq '.total_cost_usd'该 payload 包含 total_cost_usd 以及按模型细分的费用,因此 CI 作业无需使用控制面板即可记录自身开支。将该值追加到文件,或将其作为指标推送到上方的采集器。这是目前成本最低且实用的费用跟踪方式,每次运行只需进行 1 次 jq 调用。
故障模式及其表现
报告为空。 npx ccusage@latest daily 没有打印任何行,说明它读取的不是 Claude Code 写入数据的位置。CLAUDE_CONFIG_DIR 会更改该位置,因此还必须告知解析器新的位置。如果存在数据行,但最早只追溯到大约一个月前,这是 cleanupPeriodDays 的设计行为:默认情况下,转录记录会在 30 天后删除。
两台机器报告的总量不同。 这是预期行为,不是错误。/usage 和任何日志解析器都只读取本地会话历史,因此另一台设备或 claude.ai 产生的用量不会出现在两者的结果中。
本地总量与发票不一致。 本地数据根据 token 数量和标准目录价格计算。它不会考虑促销价格或合同折扣;如果使用订阅,token 也不会逐个计费。对于 API 计费,应以 Console 的用量页面为准。
执行相同工作时,成本却上升了。 首先检查缓存相关列。长会话会在每轮请求中重新发送完整历史记录:缓存有效时按缓存价格计费,缓存失效后则按完整输入价格计费。因此,长时间中断一次,就会重新处理整个对话。此时通常会看到输入数量很大,而输出数量较小;输入与输出 token 价格说明了两者为何会独立变化。
包含子代理的一天看起来不可能。 每个子代理都运行自己的上下文窗口,因此 token 用量会随运行的子代理数量及其各自持续时间增长。只有 OTel 数据能通过 query_source 属性区分它们,该属性位于 claude_code.token.usage 上。日志解析器只能显示总量,无法进一步区分。
FAQ
ccusage 会显示我在 Max 计划下实际支付的费用吗?
不会。订阅计划不是按 token 计费,因此日志解析器会按照标准 API 列表价格为 token 计价,并显示同样的工作通过 API 完成时的费用。这可以较好地反映某天的工作量,也便于比较不同项目或模型的用量。要查看实际应付金额,请使用 Console 的用量页面查看 API 计费,使用计划计费页面查看订阅费用。
Claude Code 将这些工具读取的会话文件存储在哪里?
存储在 ~/.claude/projects/<project>/<session-id>.jsonl 中,其中 <project> 是工作目录路径,非字母数字字符会替换为 -。每一行都是一个 JSON 对象,表示一条消息、一次工具调用或一项元数据。CLAUDE_CONFIG_DIR 会移动整个目录,cleanupPeriodDays in settings.json 控制 30 天的保留期限。Anthropic 将条目格式标记为内部格式,并说明不同版本之间可能发生变化,因此应使用持续维护的工具解析,而不是编写自己的脚本。
我可以将 Claude Code 遥测数据发送到 Langfuse 吗?
不能直接发送。Langfuse OTLP 端点接收 trace,而 Claude Code 导出的是 metrics 和日志事件,不是 span,因此没有对应的数据接收位置。请将 Claude Code metrics 发送到 OpenTelemetry collector,并存储到 Prometheus。对于通过 API 自行构建的 agent,可以使用 Langfuse;此时由您自己的代码生成携带 prompt、模型和费用信息的 span。
为什么本地统计数字与 Console 的用量页面不一致?
因为两者的计算方式不同。/usage 和日志解析器会汇总当前机器上会话文件中的 token 数量,然后按照标准列表价格计价。Console 会汇报组织实际支付的费用,覆盖所有机器和所有 key,并计入任何折扣。出现差异是正常的。如果差异很大,通常表示还有第二台设备、CI runner,或其他团队成员在使用同一个账户计费。
如何跟踪 CI 中一次 claude -p 运行的费用?
使用 --output-format json 运行,并从结果中读取 total_cost_usd,例如使用 claude -p "..." --output-format json | jq '.total_cost_usd'。同一负载还包含按模型划分的明细和会话 ID。按 job 记录该数值,即可获得按 pipeline 统计的费用,无需 agent、dashboard 或额外服务。