Skip to content

bodylog: export actual_usage's cached_tokens as its own counter - #31

Draft
zhanghaohit wants to merge 1 commit into
mainfrom
feat/actual-cached-tokens
Draft

zhanghaohit wants to merge 1 commit into
mainfrom
feat/actual-cached-tokens

Conversation

@zhanghaohit

Copy link
Copy Markdown
Collaborator

What

  • listener: the per-request details line (metrics/details/<date>.jsonl, what the exporter tails) gets actual_cached_tokens, taken from resp_meta.actual_usage.prompt_tokens_details.cached_tokens.
    • It is written only when that value is a number. A response without actual_usage, or with cached_tokens: null, has no field, so "not reported" and "reported 0" stay apart.
    • The DuckDB details schema gains the column. Older jsonl / parquet files read it as NULL.
  • exporter: new counter bodylog_actual_cached_tokens_total, with the same labels as bodylog_cached_tokens_total (service, route, backend, model). Only lines that carry the field feed it.

Why

bodylog_cached_tokens_total counts usage.prompt_tokens_details.cached_tokens, which is what clients and billing see. Some sglang builds also return actual_usage with the engine's own count, and it can differ:

"usage":        {"prompt_tokens": 4096, "prompt_tokens_details": {"cached_tokens": 2048, "cache_write_tokens": 1792}},
"actual_usage": {"prompt_tokens": 4096, "prompt_tokens_details": {"cached_tokens": 3072}}

Since #30 the bodylog keeps actual_usage in resp_meta, but the number reached no metric. With both counters, a dashboard can show the reported and the engine-side hit rate side by side.

Tests

  • listener TestDetailActualCachedTokens covers:
    • reported, reported 0, null, no prompt_tokens_details, and absent;
    • cached_tokens stays at usage's figure in every case;
    • the field appears on the JSON line exactly when reported.
  • exporter TestActualCachedTokensCounter: three lines with 3072 / 0 / no field. bodylog_cached_tokens_total = 3 × 2048 and bodylog_actual_cached_tokens_total = 3072. Fails on the previous metrics.go.
  • go test ./... passes in both modules.

bodylog_cached_tokens_total counts usage.prompt_tokens_details.cached_tokens --
what clients and billing see. Some sglang builds also return actual_usage with
the engine's own count, which can differ (e.g. 2048 vs 3072), and that number
reached no metric.

listener: the details line gets actual_cached_tokens, from
resp_meta.actual_usage.prompt_tokens_details.cached_tokens, only when that is a
number, so "not reported" and "reported 0" stay apart; the DuckDB details
schema gains the column (older files read it as NULL).
exporter: bodylog_actual_cached_tokens_total, same labels as
bodylog_cached_tokens_total, fed only by lines that carry the field.
@zhanghaohit
zhanghaohit marked this pull request as draft November 10, 2026 09:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant