Skip to Content
Rius

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

Rius accepts traces from the OpenTelemetry JavaScript SDK over OTLP/HTTP, so you point the exporter at the Rius ingest endpoint and send your API key in an Authorization header. Use the http/protobuf protocol, which the Node exporter package selects, and set three standard OTEL_EXPORTER_OTLP variables. Once a traced call runs, open Traces in the Rius console and check that the span shows a model, token counts and cost.

How it works

Rius ingests plain OTLP over HTTP. Traces are posted to https://ingest.eu.console.rius-glassflow.com/v1/traces with an Authorization: Bearer header that carries your API key. The endpoint accepts protobuf or JSON, and there is no gRPC endpoint. Rius ingests traces only, so OTLP metrics and logs from the same SDK are not stored.

The pieces that matter for Node.js:

  • Endpoint. With the standard environment variables you give the base URL, and the SDK adds /v1/traces. The host carries your workspace’s region. The example host is for the eu region, so use the host for your workspace’s region.
  • Protocol. http/protobuf is recommended. In Node the exporter package decides the encoding. @opentelemetry/exporter-trace-otlp-proto sends protobuf, and @opentelemetry/exporter-trace-otlp-http sends JSON, which also works.
  • Header. The API key goes in as authorization=Bearer followed by the key. The key decides which workspace the traces land in.
  • Variables do nothing alone. They take effect through the SDK. Build a tracer provider with an OTLP exporter that has no endpoint or headers set in code, or run the OpenTelemetry zero-code agent for Node.js.

Rius reads the OpenTelemetry GenAI attributes (gen_ai.*) on each span and computes cost on its side from the model and token counts. You never send a cost value. The full list of attributes Rius reads is in the span attribute reference, and the Trace LLM calls with OpenTelemetry guide compares every way of sending traces.

Set it up

  1. Create an API key in the Rius console at https://console.rius-glassflow.com. Keys start with ri_.

  2. Set the three exporter variables in the environment of your Node process. Replace the key placeholder with your own key.

    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>"
  3. Set OTEL_SERVICE_NAME to the name you want to see in Rius, for example my-agent. Also set OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=4096. OpenTelemetry’s default of 128 attributes is too low for long LLM spans that carry messages or tool definitions as one attribute per field.

  4. Start the Node SDK with the protobuf exporter and leave the endpoint and headers out of the code, so it reads the variables. NodeSDK also reads OTEL_SERVICE_NAME and the attribute limit. Shut it down before the process exits, because queued spans are not sent otherwise. The zero-code agent for Node.js works too.

    npm install @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-proto @opentelemetry/api
    import { NodeSDK } from '@opentelemetry/sdk-node' import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto' const sdk = new NodeSDK({ // No url or headers in code, so the exporter reads OTEL_EXPORTER_OTLP_* traceExporter: new OTLPTraceExporter(), // Rius ingests traces only metricReaders: [], logRecordProcessors: [], }) sdk.start() // ... your agent code ... // Flushes queued spans before the process exits (top-level await needs an ES module) await sdk.shutdown()
  5. If your libraries are not instrumented for LLM calls, emit the span yourself. This example sets everything Rius reads for a full generation: the model, token counts and messages.

    import { trace } from '@opentelemetry/api' const tracer = trace.getTracer('my-agent') const span = tracer.startSpan('chat gpt-4o') span.setAttributes({ 'openinference.span.kind': 'LLM', 'gen_ai.operation.name': 'chat', 'gen_ai.request.model': 'gpt-4o', 'gen_ai.provider.name': 'openai', }) const response = await callTheModel() span.setAttributes({ 'gen_ai.usage.input_tokens': response.usage.prompt_tokens, 'gen_ai.usage.output_tokens': response.usage.completion_tokens, 'gen_ai.response.model': response.model, 'gen_ai.output.messages': JSON.stringify([ { role: 'assistant', parts: [{ type: 'text', content: response.text }] }, ]), }) span.end()
  6. Nest spans the normal OpenTelemetry way. Wrap each agent run in one root span, because that root’s name, duration and status are what run-level views show.

  7. Run one traced call, then follow the checks below. The Vanilla OpenTelemetry SDKs page covers the same setup for other languages.

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. A call that nests under your root span appears in that one trace.
  • The span has a model, token counts and cost. Cost is a list-price estimate in US dollars, computed by Rius from the model and the token counts.
  • The service name is right. NodeSDK takes it from OTEL_SERVICE_NAME. A tracer provider you build by hand does not read that variable, so set the service name in its resource instead.

If nothing arrives, a 401 from the endpoint means the API key is wrong or revoked. If a span arrives without a model or tokens, attributes were usually lost before they reached Rius. Look for a Collector attributes or transform processor that strips gen_ai.* keys, or a span that went over the 128 attribute default, which the limit variable above prevents.

What you get is the same model, token and cost analytics as for spans sent by the Rius SDK, from code you keep in plain OpenTelemetry. Code written against raw OpenTelemetry keeps working unchanged if you later adopt a Rius SDK.

When something else fits

  • If you want LLM libraries instrumented for you, the Rius TypeScript SDK sets up the tracer provider and exporter with one init() call. The Interoperability page compares it with the sender guides.
  • If you route traces to several backends or run a gateway for many services, put an OpenTelemetry Collector between your services and Rius and use its otlphttp exporter, not otlp, which speaks gRPC.

Still stuck? Get help

Last updated on