How do I send traces from the OpenTelemetry Java SDK to Rius?
Rius accepts traces from the OpenTelemetry Java SDK over OTLP/HTTP, so you set the endpoint, protocol and Authorization header and send spans without the Rius SDK. Point the exporter at https://ingest.eu.console.rius-glassflow.com, use http/protobuf, and pass your API key as a Bearer token. Run one traced call and open it under Traces in the console to confirm it arrived.
How it works
Java has no native Rius SDK (those exist for Python and TypeScript), but the ingest endpoint is standard OTLP over HTTP, so any OpenTelemetry SDK can send to it. The Vanilla OpenTelemetry SDKs page covers this path for every language, and Trace LLM calls with OpenTelemetry compares it with the other ways in.
The pieces for Java:
- Endpoint. The base URL is
https://ingest.eu.console.rius-glassflow.com. The exporter variables append the path, so traces post tohttps://ingest.eu.console.rius-glassflow.com/v1/traces. The host carries your workspace’s region, andeuis the region documented. - Protocol. Use
http/protobuf, which is recommended.http/jsonalso works. There is no gRPC endpoint, so a gRPC exporter does not connect. - Authorization header. Send
authorization=Bearerfollowed by your API key. The key starts withri_and decides which workspace the traces land in. - Where the variables apply. The standard
OTEL_EXPORTER_OTLP_*variables take effect through the SDK, not on their own. In Java, build the SDK withAutoConfiguredOpenTelemetrySdk, which reads the protocol variable, and leave the exporter’s endpoint and headers unset in code. The zero-code Java agent reads them too.
Set it up
- Create an API key in the Rius console, which you reach at
https://console.rius-glassflow.com. Use the key for the workspace you want the traces in. - Set the exporter variables in the environment of your Java process:
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.eu.console.rius-glassflow.com"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer <your API key>"
# Rius ingests traces only, so turn off the metrics and logs exporters
export OTEL_METRICS_EXPORTER=none
export OTEL_LOGS_EXPORTER=none- Set
OTEL_SERVICE_NAMEto the name you want your agent to appear under, for examplemy-agent. Also setOTEL_SPAN_ATTRIBUTE_COUNT_LIMITto4096. The default limit of 128 attributes is too low once a span carries messages or tool definitions as one attribute per field. - Create the SDK with
AutoConfiguredOpenTelemetrySdk, or start the app with the zero-code Java agent. Do not set an endpoint or headers on the exporter in code, or they override the variables. For the SDK route, add theio.opentelemetry:opentelemetry-sdk-extension-autoconfigureandio.opentelemetry:opentelemetry-exporter-otlpdependencies. Autoconfiguration registers a shutdown hook that flushes queued spans when the JVM exits.
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
// Reads the OTEL_* variables, so no endpoint or headers in code
OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk();
Tracer tracer = sdk.getTracer("my-agent");-
Wrap each agent run in one root span and nest the model and tool spans under it. They arrive as one trace, and the root’s name, duration and status drive the run-level views.
-
Put the model details on each model-call span. A span becomes a full generation, with cost computed by Rius, when it has these attributes:
openinference.span.kindset toLLMgen_ai.operation.namegen_ai.request.modelgen_ai.provider.namegen_ai.usage.input_tokensandgen_ai.usage.output_tokensgen_ai.response.modelgen_ai.output.messages
Do not send a cost attribute. The Vanilla OpenTelemetry SDKs example shows these keys on one span.
If you use instrumentation that already emits gen_ai.* attributes, you do not set them yourself.
What you get
- Traces from your Java service in the Rius trace list, with the span tree you built.
- For each model-call span with the attributes above, the model name, token counts and a cost shown as a list-price estimate in US dollars.
- Spans that arrive without a model or tokens are still stored. Their detail depends on which attributes your instrumentation emits.
After the first run, check these in order:
- Open Traces in the console and open the new trace. The model-call span should show a model name, token counts and cost.
- If nothing arrives, a
401from the endpoint means the API key is wrong or revoked. - If a span arrives without a model or tokens, check that no Collector
attributesortransformprocessor stripsgen_ai.*keys. Also check that the span stays under the attribute count limit you set. - If you send through a Collector, give its
otlphttpexporter the base URL. Useotlphttp, nototlp, which speaks gRPC.
The Interoperability section lists the sender guides and the attribute contract.
When something else fits
- For a Python or TypeScript service, the Rius SDK sets up the exporter for you and adds message normalization, export-time privacy controls and auto-instrumentation of LLM libraries.
- If several services or backends share one pipeline, send through an OpenTelemetry Collector with the
otlphttpexporter and add Rius as one more entry. - Rius ingests traces only. Autoconfiguration also starts metrics and logs exporters aimed at the same endpoint, so turn them off with the two variables in step 2.