Skip to Content
DocsTracesToken Costs

Token Costs

Rhesis prices a trace by multiplying the tokens each LLM call reported by the published per-token rate for that model, in USD.

Pricing runs as part of enrichment, which is dispatched asynchronously after a trace is ingested. Tokens therefore appear on a trace immediately while cost appears a moment later, and a trace opened the instant it arrives shows tokens with no cost yet.

Where the rates come from

Rhesis does not keep its own price list. Rates come from LiteLLM’s model database , which ships with the backend and covers the commercial providers and their published per-token prices for input and output separately.

A model that database does not know gets no cost recorded at all. Its tokens are still counted, and the trace reads as having no cost data rather than as a free run. That happens for a self-hosted or private deployment, and for a model newer than the LiteLLM version the backend was built against.

What gets priced

Only spans whose ai.operation.type attribute is llm.invoke are priced. Two kinds of span carry token counts but are deliberately left out:

  • Agent-run spans. Frameworks such as Pydantic AI report aggregated usage on the agent-run span and per-call usage on each child model call. Counting both would roughly double the trace.
  • Embedding spans. They carry ai.llm.tokens.* attributes but their operation type is embedding.create. Pricing them would put the token total and the cost total on different footings.

A trace with no llm.invoke spans has no cost at all, not a cost of zero. Neither has a span that reported no tokens: there is nothing to multiply the rate by, and a call that used nothing is almost always one whose reply Rhesis could not read rather than one that was free.

When a figure is missing

Rhesis distinguishes “not known” from “nothing spent”. A number it does not have is left blank rather than shown as zero, so an empty cost never reads as a free run. The cost card says No cost data for that case, and a trace with no cost shows a dash in the list rather than a figure.

What you seeWhat it means
No cost data, tokens presentNo model in the run could be priced
No cost data, no tokens eitherThe calls reported no tokens, so there was nothing to price
Working out what this cost, tokens presentEnrichment has traces of this run left to price
A cost of zeroThe run was priced and came to nothing, for example on a free tier
Cost present, no input/output splitThe trace was priced before Rhesis recorded the two halves separately
Provider shown as unknownThe span reported no provider and its model name could not be placed

A span that cannot be priced still contributes its tokens. Dropping it would make a trace that mixes priced and unpriced models undercount what it actually used.

Cached prompts

Providers that cache prompts bill those tokens at their own rates: writing a cache costs more than an ordinary input token, reading one costs far less. Rhesis records the two counts separately, as ai.llm.tokens.cache_write and ai.llm.tokens.cache_read, and prices each at its own rate.

ai.llm.tokens.input is the uncached part alone, which is why a trace’s total is the input plus the output plus the cached tokens. A call that read 4,000 tokens from cache beside 50 fresh ones therefore reports 4,070 tokens and a cost covering all of them.

Traces recorded before Rhesis kept these counts report no cached tokens and price exactly as they did before, since there is nothing to charge them for.

Providers

The provider is read from the ai.model.provider span attribute where the span carries one. An integration sets it when it can place the call: from the framework’s own report, from the module or class that made it, or from the model name. Where it cannot, it sets nothing rather than guessing, and Rhesis derives the provider from the model name instead. That fallback is also what covers raw OTLP and any framework Rhesis does not translate. Where neither works, the provider is recorded as unknown.

Provider names are normalised so one provider appears once. LiteLLM names providers by how it routes to them, which splits some into two: a bare gemini-2.0-flash is vertex_ai to LiteLLM while the Google ADK integration reports gemini for the same call. Rhesis folds those onto a single name.

Currencies

USD is the stored figure. Costs can be shown in USD, EUR, GBP or CHF, converted from the stored figure at the current rate rather than read from a second stored one, so every figure on a screen is on the same basis.

Rates come from Frankfurter , which republishes European Central Bank reference rates. The ECB sets those once per working day, so the rates are daily rather than real-time, and Rhesis caches them for a day. Hovering a cost shows the same figure in the other currencies and the day the rates are from.

Pick the currency in two places. An organization sets the default under Settings → Preferences, which everyone sees unless they choose otherwise. An individual overrides it under their own Settings → Preferences, or chooses to follow the organization.

Set USD_TO_EUR_RATE to pin a fallback rate for an instance with no outbound network access. It covers EUR only, which is all it has ever covered — with no rates available, the other currencies are not offered and costs show as stored rather than being converted at a guess.

Accuracy

Two things to know when reconciling a Rhesis figure against a provider invoice.

Per-span costs are rounded to six decimal places before being summed, so input cost plus output cost can differ from the total by a fraction of a cent on a trace with many spans.

Rhesis prices what the instrumented call reported. Discounts, committed-use pricing and batch rates are not applied, so a figure here is list price for the tokens observed.