How do I track LLM cost per end user?
Rius splits LLM cost per end user when your spans carry a user.id, and it shows each user’s total and average cost on the Users page and over MCP. Rius prices every model call from the model name and token counts, then rolls the cost up to the user on the spans. You never send a cost value. Sort the Users page by Cost, or ask your MCP client for your most expensive users, to see who drives spend.
How it works
Two things on the spans produce a per-user cost.
- An end user on the span. Rius reads
user.id,enduser.idorenduser.pseudo.idand takes the first one that is set. The SDKs setuser.idon every span of a request that runs inside a user scope:rius.userin Python,withUserin TypeScript. A trace with no end user on any span counts as anonymous. - A priced model call. Rius looks up the requested model (
gen_ai.request.model) and multiplies the token counts from thegen_ai.usage.*attributes by that model’s rates, including prompt-cache reads and writes. A span that carries onlygen_ai.response.modelis not priced.
A user’s cost is the sum of their priced calls. If a model has no price, or the span reported no token usage, the call’s cost is empty rather than zero, so it adds nothing to the user’s total. Costs are list-price estimates in US dollars from LiteLLM’s public model-price catalog. They do not include negotiated discounts, batch pricing or long-context tiers, so expect your invoice to differ.
The per-user figures count finished traces only. A run appears once every span of it has ended.
Set it up
-
Install the SDK and call
initonce at startup. The full setup is in Track LLM and agent cost and the quickstart.import rius client = rius.init( api_key="ri_...", service_name="my-agent", ) -
Run each request inside a user scope, using
rius.userin Python orwithUserin TypeScript. With plain OpenTelemetry, setuser.idas a span attribute yourself. Set it on every span, root included. Prefer an opaque ID such as an internal account number to an email address. -
Check that the model calls are priced. The span for each model call needs
gen_ai.request.modeland its token counts. The Rius SDK integrations record these for you. -
Verify in one minute. Run one request in a user scope with a test ID such as
test-user-1. Open Users, typetest-user-1, click Find and open the row. Once the trace has finished, the page shows 1 trace, your agent under Agents that served this user, and the trace under Recent traces. -
Read the split. In the console, open Users and sort by Cost. Over MCP, ask your client:
Who were my ten most expensive end users this week?
The client calls
list_userssorted by cost. It can calluser_activity_summaryfor one user, and the trace tools accept auser_idargument to narrow runs to that user.
Coding agents follow the same rule. With version 0.6.2 or later of the Rius plugin, Claude Code sessions, and Codex (beta) and Cursor (beta) sessions, carry the developer’s sign-in email as user.id, so they show up by developer. For OpenHands, pass user_id to Conversation.
What you get
- A ranked list of users. On Users, each row shows traces, failed traces, cost, the agents that served the user and when they were last seen. Choose a window of 15m, 1h, 1d, 7d (the default) or 30d, and sort by traces, failed traces or cost. The list shows the top 50 users for the sort, so search by the exact user ID to reach anyone else.
- A page per user. The Cost tile shows total cost and average cost per trace. Compare it with the agent’s average to see whether a user is well above normal, for example because of longer history, harder questions or retries.
- Coverage you can read. A line above the list says how many traces carry an end user, for example “400 of 471 traces carry an end user”. Everything else sits in the anonymous row, which always comes first. A large anonymous row means some code paths run outside a user scope.
- From a user to the runs behind the cost. Click Traces on a user’s page to open the trace list filtered to them, then open a trace to see the cost of each model call.
- The workspace context. Usage and cost shows the workspace total for the period, cost by model and the change against the previous period, so you can place one user’s spend against the whole.
- Alerts. Cost is a metric in custom alerts, measured per trace, if you want a notification when runs get expensive.
When something else fits
If each customer has their own workspace, that workspace’s total is the customer’s cost, and you do not need user tagging. Within one workspace, use user.id and the Users page. If you need a spend or budget threshold for the whole workspace, watch it on Usage and cost, because total spend is not an alert metric today.