Skip to Content

How do I get LLM cost with OpenInference instrumentors?

Rius computes LLM cost for OpenInference instrumentors on its own, from the model name and token counts they already record, so you send no cost attribute. Point an OTLP exporter at the Rius ingest endpoint and raise OpenTelemetry’s span attribute limit to 4096. OpenInference does not raise that limit for you, and without it a long agent run can lose the model and token counts that cost needs.

How it works

Rius prices a call from gen_ai.request.model plus the gen_ai.usage.* token counts: input, output, cache read and cache write, each at its own rate. OpenInference instrumentors do not write those keys. They write their own, and Rius maps them at ingest:

  • The request model comes from llm.request.model_name, else the model member of llm.invocation_parameters, else llm.model_name. It lands on gen_ai.request.model.
  • llm.token_count.prompt and llm.token_count.completion, with their cache and reasoning details, fill the gen_ai.usage.* counts.
  • Keys you already send under gen_ai.* always win. The mapping fills gaps and never overwrites.

So the attributes cost needs are set for you by the instrumentor, and Rius renames them. The one thing that can break this is span size. OpenInference writes one attribute per message field and per tool field, and OpenTelemetry keeps only 128 attributes per span by default, dropping the rest without an error. An agent loop with about ten tools can pass that after six to nine turns. The span then loses attributes such as the model, tool definitions, usage and output, and a span with no model or no token counts gets no cost.

A span also gets no cost when its model is not in the price catalog. Costs are list-price estimates in US dollars from LiteLLM’s public model-price catalog, and an unknown model shows an empty cost, not zero.

Set it up

  1. Create an API key in the Rius console. The key decides which workspace the traces land in.
  2. Build a tracer provider with the attribute limit raised, add an OTLP exporter for the ingest endpoint, and pass the provider to the instrumentor. This exporter takes the full /v1/traces path:
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 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)
  1. In any other language, or when you cannot edit the provider code, raise the limit through the environment instead:
export OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=4096
  1. Run one traced LLM call, open Traces in the console, and open the new trace. The span for the model call shows the model name, token counts and cost.
  2. If the cost is empty, open the span and check two things: that a model name and at least one token count are present, and that the model is one the price catalog knows. Do not add a cost attribute. Rius ignores a cost attribute and computes cost from the model and tokens.

The Rius Python and TypeScript SDKs ship these same instrumentors and set the 4096 limit for you, so if your app is in either language you can skip steps 2 and 3. The general ways to send traces, including the Collector, are in Trace LLM calls with OpenTelemetry.

What you get

  • A cost on each model-call span, estimated in US dollars from the model and token counts, with cache reads and writes priced at their own rates.
  • Cost totals and a per-model breakdown across your traces, with no pricing code in your app.
  • Searchable values under the gen_ai.* keys. Filter on gen_ai.usage.input_tokens, not on llm.token_count.prompt, because the OpenInference source keys are removed once mapped.
  • Spans that keep their model, tools and usage on long agent runs, because the attribute limit no longer drops them.

The OpenInference page covers what else is captured, and the span attribute reference lists every attribute Rius reads and the full mapping.

When something else fits

  • If you need prices that differ from list prices, such as negotiated, batch or priority discounts, Rius does not apply them, so treat its cost as an estimate and reconcile against your provider invoice.
  • If you are on Python or TypeScript and want less wiring, the Rius SDK applies the same OpenInference mapping and the raised limit for you.

Still stuck? Get help

Last updated on