[BUG] claude_code_cost_usage_USD_total metric semantics appear inconsistent with Prometheus Counter behavior

Open 💬 1 comment Opened Jun 12, 2026 by navnitkum

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_

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗