Skip to Content

What does the user.id attribute mean in Rius?

In Rius, user.id is a string attribute that names the end user a request served, and it groups traces by user on the Users page. Set it on every span in scope. A span with no user id counts as anonymous. Rius also reads enduser.id and enduser.pseudo.id when user.id is absent.

How it works

  • What it holds. The key holds one string, the identifier of the end user your agent served. It is not the developer or the service. Prefer an opaque id to an email address.
  • Which spans carry it. Put it on every span of the trace, root included. Rius reads it per span, so a span without it is not attributed to the user even if the root span has it.
  • Alternative names. When user.id is absent, Rius reads enduser.id first, then enduser.pseudo.id. For Laminar spans, Rius reads lmnr.association.properties.user_id as the user. If a span has none of these, it is anonymous.
  • How the value is stored. A user.id sent by OpenInference or by you is stored as sent, under the key user.id.
  • What Rius derives from it. Rius groups traces by user. For each user, the Users page shows their traces, failures, cost and time to first token. Cost is computed by Rius from the model and token counts on each span, so you never send a cost value.
  • Why you set it per span. The same rule applies to session.id. If you want both session and user views to be complete, stamp both on every span.

The full attribute list is in the span attribute reference.

Set it up

  1. With the Rius SDK, use its user scope. The Python SDK stamps user.id for you through rius.user, and the TypeScript SDK does it through withUser. There is no environment variable for user.id, by design, because a process-wide value would attribute every request to the same person. Initialize the SDK once, as in this Python example. The Trace LLM calls with OpenTelemetry guide covers the wider setup.
import rius client = rius.init( api_key="ri_...", service_name="my-agent", ) with rius.user(request.user_id): handle(request) # every span of the request carries user.id
  1. With a vanilla OpenTelemetry SDK or a collector, set the attribute yourself. Add user.id to every span you emit for that request, not only the root span. Third-party senders set it directly, because only the SDK scopes stamp it for you.
  2. Choose the value carefully. Use a stable, opaque identifier such as an internal account id. Use the same value for the same person across requests, so their traces group together.
  3. If you already emit enduser.id or enduser.pseudo.id, you can leave them. Rius reads them when user.id is missing. If a span carries more than one, user.id wins, then enduser.id, then enduser.pseudo.id.
  4. Check the result. Open the Users page after a few requests. Each distinct value should appear as one user with its traces and cost. If everything lands under anonymous, the attribute is missing from the spans or sits only on a span that is not in scope.
  5. Keep the attribute from being dropped. OpenTelemetry SDKs keep at most 128 attributes per span and drop the rest without an error. The Rius SDKs raise the limit to 4096. If you export without them, set it yourself:
export OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=4096

What you get

  • A Users view of each end user your agents served, with their traces, failures, cost and time to first token.
  • Cost per user as a list-price estimate in US dollars, computed by Rius from the model and token counts on the spans.
  • A clear split between identified users and anonymous traffic, so you can see how much of your volume has no user id.
  • Compatibility with what you already emit. Spans that use enduser.id, enduser.pseudo.id, or Laminar’s user_id association property group by user without renaming anything.
  • Grouping that matches session grouping, because both keys follow the same per-span rule.

When something else fits

  • If you do not need per-user views, leave user.id unset. Your traces still work, and they count as anonymous.
  • If you want to group traces by a conversation or an agent run rather than by person, use session.id instead. It is a separate key with its own grouping.

Still stuck? Get help

Last updated on