How does Rius read OpenInference model name attributes?
Rius reads the model name from OpenInference’s llm.request.model_name, the model member of llm.invocation_parameters, or llm.model_name, and stores it as gen_ai.request.model at ingest. The provider-reported model is stored as gen_ai.response.model. With the model and token counts in place, OpenInference spans get model analytics and server-side cost like native spans.
How it works
OpenInference instrumentors emit standard OpenTelemetry spans. When Rius ingests them, it moves the values from the OpenInference attribute names onto the gen_ai.* keys and removes the source keys it mapped. This is called normalizing at ingest.
Request model. Rius takes the first of these that is set:
llm.request.model_name- the
modelmember ofllm.invocation_parameters llm.model_name
The result is stored as gen_ai.request.model. Inside llm.invocation_parameters, model_name is also accepted as a fallback for model.
Response model. Rius takes llm.response.model_name, else llm.model_name, and stores it as gen_ai.response.model. The llm.model_name fallback applies only when the span’s status is OK. On an ERROR or UNSET span, Rius does not use llm.model_name for the response model, because on those spans it may still hold the model you requested rather than the one the provider served.
Precedence. Native gen_ai.* keys always win. Normalization fills gaps and never overwrites a value the span already carries.
Tokens and cost. llm.token_count.prompt and llm.token_count.completion, with their cache and reasoning details, fill the token counts. Rius computes cost on the server from gen_ai.request.model and those counts. A span with no model, a model the price catalog does not know, or no counts gets no cost.
The Rius SDKs apply the same mapping in your process before export, with one difference: they skip the llm.model_name fallback, which only the platform applies.
Set it up
- Install the OpenInference instrumentor for your library and wire it to the Rius ingest endpoint with an OTLP exporter. This example uses the OpenAI instrumentor. The full setup, including the exporter details, is on the OpenInference page.
from opentelemetry.sdk.trace import SpanLimits, TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from openinference.instrumentation.openai import OpenAIInstrumentor
# Raise the attribute limit: see "Raise the span attribute limit" below.
provider = TracerProvider(span_limits=SpanLimits(max_span_attributes=4096))
provider.add_span_processor(
BatchSpanProcessor(
OTLPSpanExporter(
endpoint="https://ingest.eu.console.rius-glassflow.com/v1/traces",
headers={"Authorization": "Bearer <your API key>"},
)
)
)
OpenAIInstrumentor().instrument(tracer_provider=provider)- Raise the span attribute limit. OpenInference writes one attribute per message field and per tool field, and OpenTelemetry keeps only 128 attributes per span by default. Past that, a span silently loses attributes, and the model can be one of them. The code above sets the limit in Python. For any language, set it through the environment:
export OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=4096-
Set the status on your spans as your instrumentor normally does. Rius uses an OK status to decide whether
llm.model_namecan fill the response model. -
Search and filter on the canonical keys,
gen_ai.request.modelandgen_ai.response.model. A filter onllm.model_namematches nothing, because that source key is removed once it is mapped.
For how this fits next to the other ways of sending traces, see Trace LLM calls with OpenTelemetry.
What you get
- Your OpenInference spans carry
gen_ai.request.modeland, when the provider reports it,gen_ai.response.model, so model analytics work without changing your instrumentation. - Cost per call is computed by Rius from the model name and the token counts. Costs are list-price estimates in US dollars from LiteLLM’s public model-price catalog, and a model the catalog does not know gets an empty cost.
- A span whose OpenInference kind is
LLM, or that carriesgen_ai.request.modeland has no kind or operation, is counted as an LLM call in the console and in alerts. - Request parameters in
llm.invocation_parameters, such astemperatureandmax_tokens, becomegen_ai.request.*keys, andtool_choicebecomesrius.request.tool_choice. - Values already set on
gen_ai.*keys are kept as sent.
The span attribute reference has the full supported-conventions matrix, and the interoperability overview lists the other sender guides.
When something else fits
- If you emit spans yourself, set
gen_ai.request.modeland thegen_ai.usage.*token counts directly. That skips the mapping and makes the model name explicit. - If you use Python or TypeScript and want the exporter, attribute limit and privacy controls wired for you, use the Rius SDK integrations instead of running OpenInference on its own.