Skip to Content
Rius

Can I send traces from OpenInference instrumentors to Rius unchanged?

Yes, Rius reads spans from OpenInference instrumentors as they are, and you only point an OTLP exporter at the Rius ingest endpoint. Rius maps the OpenInference attributes onto the OpenTelemetry GenAI attributes when the spans arrive, so each call gets model analytics, token usage and cost. The instrumentor stays as it is. You change the exporter’s endpoint and add an API key header.

How it works

OpenInference instrumentors emit standard OpenTelemetry spans, so any OTLP exporter can carry them to Rius. The ingest endpoint accepts OTLP over HTTP, as protobuf or JSON. It has no gRPC endpoint, so use an HTTP exporter such as the Python otlp.proto.http class.

What Rius reads from the spans as they are:

  • openinference.span.kind sets the span type, such as LLM, TOOL or CHAIN.
  • input.value and output.value are captured as the span’s content.
  • The LLM detail attributes, llm.model_name, llm.provider, llm.token_count.*, llm.invocation_parameters, llm.tools.* and llm.input_messages.*, are normalized into their gen_ai.* equivalents at ingest.
  • On streamed calls from the Python OpenAI instrumentor, the first-token event becomes gen_ai.first_token, which feeds time to first token.

The normalized values are stored under the gen_ai.* keys. Search and filter on gen_ai.usage.input_tokens, not on llm.token_count.prompt. Rius computes cost on its side from the model and token counts, as a list-price estimate in US dollars, so you never send a cost value. The OpenInference page has the full mapping, and the Interoperability section covers the other sender paths.

Set it up

  1. Create an API key in the Rius console. The key decides which workspace the traces land in.
  2. Give your tracer provider an OTLP exporter that points at Rius, and pass that provider to the instrumentor. This example raises the attribute limit at the same time. The exporter takes the full /v1/traces path, because it does not append it for you.
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 so long agent loops keep their usage and model 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. Raise the span attribute limit if you configure OpenTelemetry through the environment, or in a language other than Python. OpenInference writes one attribute per message field and per tool field, and OpenTelemetry keeps only 128 attributes per span by default. An agent loop with about ten tools passes that after six to nine turns, and the span then silently loses attributes such as the model, tool definitions and usage. The environment variable works in any language:
export OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=4096
  1. In Node, use @opentelemetry/exporter-trace-otlp-proto for protobuf. The similarly named @opentelemetry/exporter-trace-otlp-http sends JSON, which also works.
  2. Run one instrumented call and open the new trace in the console. The LLM span shows a model name, token counts and cost. The Trace LLM calls with OpenTelemetry guide covers troubleshooting if nothing arrives.

What you get

  • Spans from your existing OpenInference instrumentors appear as traces, with the span type taken from openinference.span.kind.
  • Model analytics, token usage and a server-side cost estimate for each LLM call, with no re-instrumentation.
  • Time to first token on streamed calls from the Python OpenAI instrumentor.
  • Prompt and output content from input.value and output.value.

You may still want to add a few things:

  • A higher attribute limit, so long agent loops keep every attribute.
  • session.id and user.id on every span, root span included. With no session.id each trace is its own session, and with no user.id the traffic counts as anonymous. Prefer an opaque user id to an email.
  • A service.name on your resource, so your agent is grouped under a name you recognize.

Without the Rius SDK there are no privacy controls running in your process. Everything the instrumentor records, including the full request-parameter bag, is sent as recorded.

When something else fits

If your app is Python or TypeScript and you want privacy controls, the attribute limit and the exporter wired for you, the Rius SDK ships these same instrumentors as integrations. The Trace LLM calls with OpenTelemetry guide compares every path side by side. If you route traces through an OpenTelemetry Collector, add Rius as one more exporter there instead.

Still stuck? Get help

Last updated on