Skip to Content
Rius

How do I send traces from the OpenTelemetry Go SDK to Rius?

Rius accepts traces from the OpenTelemetry Go SDK over standard OTLP/HTTP, so you point the exporter at the Rius ingest endpoint and add an Authorization Bearer header with your API key. Use the HTTP protobuf protocol, because there is no gRPC endpoint. The first trace shows up under Traces in the console, with a model name, token counts and cost on each LLM span. This is the vanilla OpenTelemetry path from the OpenTelemetry guide, with no Rius SDK needed.

How it works

Go has no native Rius SDK, so you use the standard OpenTelemetry exporter settings. Go reads the same exporter variables as every other OpenTelemetry SDK, when the exporter is built from its defaults.

  • Endpoint: the ingest host for your workspace’s region, https://ingest.eu.console.rius-glassflow.com for eu. Rius receives traces at /v1/traces on that host. When you set the endpoint through the environment variable, you give the base URL and the exporter adds the path. The full URL is https://ingest.eu.console.rius-glassflow.com/v1/traces.
  • Protocol: OTLP over HTTP, http/protobuf recommended, http/json also accepted. gRPC is not available. In Go, the exporter package you import decides the protocol, so import the OTLP trace exporter that speaks HTTP, not the gRPC one.
  • Header: Authorization: Bearer followed by your API key. The key also decides which workspace the traces land in.
  • Signals: Rius ingests traces only, not OTLP metrics or logs.

The variables take effect through the SDK, not on their own. Register a tracer provider with the HTTP OTLP exporter and leave the endpoint and headers out of your code, so the exporter picks them up from the environment.

Rius reads the OpenTelemetry GenAI attributes (gen_ai.*) on each span. A span becomes a full generation, with cost computed by Rius, when it carries the model, token counts and messages.

Set it up

  1. Create an API key in the console at https://console.rius-glassflow.com. Keys start with ri_.
  2. Set the exporter variables in the environment of your Go process. Use your workspace’s region in the host if it is not eu.
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>" export OTEL_SERVICE_NAME="my-agent" # Keep long LLM spans whole; the default of 128 attributes is too low export OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=4096
  1. Register a tracer provider in your Go code with the OTLP HTTP trace exporter, and set no endpoint or headers on it. Because the exporter reads the variables, your key stays out of the source. Shut the provider down before the process exits, or queued spans are lost.
import ( "context" "log" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" sdktrace "go.opentelemetry.io/otel/sdk/trace" ) func main() { ctx := context.Background() // No endpoint or headers in code, so the exporter reads OTEL_EXPORTER_OTLP_* exporter, err := otlptracehttp.New(ctx) if err != nil { log.Fatal(err) } provider := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter)) defer provider.Shutdown(ctx) // flushes queued spans before the process exits otel.SetTracerProvider(provider) // ... your agent code ... }
  1. Wrap each agent run in a single root span and nest the model calls and tool calls under it with the normal parent context. Rius shows that root’s name, duration and status in run-level views, and the nested spans arrive as one trace.

  2. On each model-call span, set the attributes that drive analytics:

    • openinference.span.kind set to LLM
    • gen_ai.operation.name
    • gen_ai.request.model
    • gen_ai.provider.name
    • gen_ai.usage.input_tokens and gen_ai.usage.output_tokens, set after the call returns
    • gen_ai.response.model

    Never send a cost attribute, because Rius computes it. The vanilla OpenTelemetry SDKs page shows a complete example span, written in TypeScript, with every attribute and the message shape. The attribute names are the same in Go.

  3. Run the process once so it makes one traced model call.

What you get

Once the first trace arrives, check these in order:

  • The trace is listed. Open Traces in the console and open the new trace. If nothing appears, check the workspace: the API key decides where traces land, so a key from a different workspace sends them elsewhere.
  • No 401. A 401 from the endpoint means the API key is wrong or revoked. Confirm the header reads authorization=Bearer followed by a key that starts with ri_.
  • The span carries a model and tokens. The model-call span should show a model name, input and output token counts, and cost. Rius prices the span from the model and token counts, in US dollars, as a list-price estimate. A model Rius does not know gets an empty cost, not zero.
  • Attributes survived the trip. If a span arrives without a model or tokens, an attribute was lost. Confirm you set the attribute count limit to 4096, because the default of 128 is too low for spans that carry messages or tool definitions as one attribute per field. If a Collector sits in between, make sure no processor strips the gen_ai.* keys.
  • One trace, nested. Your model calls and tool calls should appear under the root span for the run, not as separate traces.

From there you get the trace list with search and filters, a waterfall of each run, and cost and token totals, the same views as for traces sent by any other route.

When something else fits

  • If your service is in Python or TypeScript, the native Rius SDK adds message normalization, a raised attribute limit, privacy controls and auto-instrumentation on top of the same protocol. Raw OpenTelemetry code keeps working if you adopt it later.
  • If you route or fan out traces to several backends, put an OpenTelemetry Collector in front of Rius. The sender guides under Interoperability cover that setup.

Still stuck? Get help

Last updated on