OpenInference
OpenInference instrumentors (the ones behind Arize Phoenix) work with Rius directly: they emit standard OpenTelemetry spans, so they only need an OTLP exporter pointed at the ingest endpoint.
The Rius SDKs ship these same instrumentors as integrations and wire the exporter, the span attribute limit, privacy controls, and reliability behavior for you. This page is for running OpenInference without the SDK.
Wiring an instrumentor
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)Note the exporter class: otlp.proto.http (protobuf over HTTP). The
endpoint also accepts OTLP/JSON, but no gRPC. In Node, use
@opentelemetry/exporter-trace-otlp-proto; the similarly named
@opentelemetry/exporter-trace-otlp-http sends JSON, which works too.
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. An agent loop with about ten tools passes that after six to nine turns, and from then on the span silently loses attributes: the model, request parameters, tool definitions, and system prompt in Python, the usage, output, and finish reason in Node. Raise the limit, either in code as above or for any language through the environment:
export OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=4096The Rius SDKs set 4096 for you.
What gets captured
openinference.span.kind drives the span taxonomy (LLM, TOOL,
CHAIN, …), input.value / output.value are captured as span content, and
the LLM detail attributes (llm.model_name, llm.provider,
llm.token_count.*, llm.invocation_parameters, llm.tools.*,
llm.input_messages.*) are normalized into their gen_ai.* equivalents at
ingest, so OpenInference-instrumented calls get model analytics, token
usage, and server-side cost like native spans. The normalized values are
stored under the gen_ai.* keys, so search and filter on those, such as
gen_ai.usage.input_tokens rather than llm.token_count.prompt. On
streamed calls from the Python OpenAI instrumentor, the first-token event is
likewise normalized to gen_ai.first_token, feeding time-to-first-token.
Without the SDK there are no privacy controls in your process: everything the instrumentor records, including the full request-parameter bag, is sent as recorded.
Details of the mapping, including the native-wins precedence rule, are in the supported-conventions matrix.
Next steps
- Integrations: the same instrumentors, wired by the SDK, if your app is Python.
- Span attribute reference: the full normalization contract.