[BUG] claude_code_cost_usage_USD_total metric semantics appear inconsistent with Prometheus Counter behavior
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Summary
We're integrating Claude Code telemetry with:
Claude Code
→ OpenTelemetry Collector
→ VictoriaMetrics
→ Grafana
and are observing behavior from the metric:
claude_code_cost_usage_USD_total
that appears inconsistent with expected Prometheus Counter semantics.
According to the telemetry documentation, this metric is exposed as:
Metric: claude_code_cost_usage_USD_total
Type: Counter
Description: Estimated cost in USD
However, the exported series behave more like per-session snapshots than cumulative counters.
Environment
Collector
OpenTelemetry Collector Contrib 0.122.0
Storage
VictoriaMetrics
Visualization
Grafana
Claude Code
Latest version (June 2026)
Observed Metric Labels
Example metric:
claude_code_cost_usage_USD_total
with labels such as:
user_email
organization_id
model
session_id
query_source
terminal_type
user_id
user_account_id
user_account_uuid
skill_name
plugin_name
marketplace_name
mcp_server_name
mcp_tool_name
What Should Happen?
Since the metric is documented as a Prometheus Counter, we expected each series to behave like:
0
1
2
3
4
5
...
or
10.1
10.4
11.2
11.7
12.0
...
(monotonically increasing over time)
and therefore support standard PromQL functions such as:
increase(claude_code_cost_usage_USD_total[5m])
rate(claude_code_cost_usage_USD_total[5m])
What We Actually Observe
Query:
claude_code_cost_usage_USD_total{
user_email="jaffer.sadeg"
}
returns multiple series such as:
23.0
11.3
10.6
5.61
2.48
0.33
...
These values remain constant for long periods and do not appear to increase over time.
Example:
session A -> 23.0
session B -> 11.3
session C -> 10.6
The series appear to behave more like:
total cost of session
rather than:
cumulative counter
Error Messages/Logs
To build a "Top Users by Cost" dashboard we tried:
topk(
10,
sum by (user_email)(
increase(
claude_code_cost_usage_USD_total[$__range]
)
)
)
However results appear inconsistent.
We also observed that:
sum by(user_email)(
claude_code_cost_usage_USD_total
)
often produces values that appear to be the sum of many session-level costs.
Questions
1. Is claude_code_cost_usage_USD_total truly a Prometheus Counter?
Specifically:
Is it expected to be monotonic?
Is increase() the correct PromQL function?
2. Is the metric actually session-scoped?
The observed behavior suggests each unique combination of:
session_id
model
query_source
produces a separate series whose value represents the final cost for that session.
If this is expected, then the metric behaves more like:
cost_per_session
than a cumulative counter.
Can you clarify the intended semantics?
3. What is the recommended PromQL for:
Cost during selected time range
Last 5m
Last 1h
Last 24h
Lifetime cost by user
Top users by cost
4. Are high-cardinality labels intentional?
Current labels include:
session_id
user_id
user_account_id
user_account_uuid
skill_name
plugin_name
marketplace_name
mcp_server_name
mcp_tool_name
query_source
These generate a very large number of unique time series.
Is this expected?
Are there recommended labels to drop when exporting into Prometheus/VictoriaMetrics?
Steps to Reproduce
Enable Claude Code telemetry and export metrics to a Prometheus-compatible backend (Prometheus, VictoriaMetrics, etc.).
Generate Claude Code activity using multiple sessions, models, and subagents.
Query the cost metric:
claude_code_cost_usage_USD_total
Observe that the metric is exported with labels such as:
user_email
organization_id
model
session_id
query_source
terminal_type
user_id
user_account_id
user_account_uuid
skill_name
plugin_name
marketplace_name
mcp_server_name
mcp_tool_name
Query a specific user:
claude_code_cost_usage_USD_total{
user_email="jaffer.sadeg"
}
Observe multiple time series for the same user, for example:
23.0
11.3
10.6
5.61
2.48
...
with different combinations of:
session_id
model
query_source
Inspect the series over time.
Observe that many series appear to remain constant for long periods rather than monotonically increasing.
Run:
increase(
claude_code_cost_usage_USD_total[5m]
)
Observe that some series report large increases while the underlying raw series appear to behave like session-level cost snapshots.
Aggregate by user:
sum by (user_email) (
increase(
claude_code_cost_usage_USD_total[5m]
)
)
Compare the resulting values with the raw series and attempt to build a "Top Users by Cost" dashboard.
Expected Behavior
claude_code_cost_usage_USD_total is documented as a Prometheus Counter.
Therefore each time series should:
Be monotonically increasing
Support increase() and rate()
Produce intuitive cost aggregation when grouped by user_email
Example:
10.1
10.5
11.2
12.0
12.7
...
Actual Behavior
The metric appears to be partitioned by:
session_id
query_source
model
and many series appear to behave like session-level cost totals rather than cumulative counters.
This makes it difficult to determine:
Whether increase() is the correct query function
Whether costs are being double-counted across sessions
How to correctly calculate user-level spend over a time range
Which labels are required for accurate cost reporting
Claude Model
None
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.175 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗