Ratel Docs
Telemetry

Send telemetry

Point any OpenTelemetry exporter at Ratel Cloud. No Ratel SDK needed.

Ratel Cloud ingests standard OpenTelemetry traces. Any agent that emits LLM spans can send them, in any language.

Using the Ratel SDK already? See Observe your agent instead.

What you need

  • A project API key. Create one in your project's Settings > API keys on cloud.ratel.sh.
  • An OTLP/HTTP trace exporter. Protobuf and JSON both work; gRPC does not.
SettingValue
Endpointhttps://cloud.ratel.sh/v1/traces
HeaderAuthorization: Bearer <your-key>
Protocolhttp/protobuf or http/json

Configure with environment variables

Most OpenTelemetry SDKs read these at startup:

export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://cloud.ratel.sh/v1/traces"
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="Authorization=Bearer%20$RATEL_API_KEY"
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="http/protobuf"
# Send message content so Cloud can break down what fills the context:
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT="true"

The space after Bearer is URL-encoded as %20.

Or configure in code

pip install opentelemetry-sdk opentelemetry-exporter-otlp-proto-http \
  opentelemetry-instrumentation-openai-v2
import os
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor

provider = TracerProvider()
provider.add_span_processor(
    BatchSpanProcessor(
        OTLPSpanExporter(
            endpoint="https://cloud.ratel.sh/v1/traces",
            headers={"Authorization": f"Bearer {os.environ['RATEL_API_KEY']}"},
        )
    )
)
trace.set_tracer_provider(provider)
OpenAIInstrumentor().instrument()

Every OpenAI call is now traced. Set OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true to include message content.

npm install @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-proto
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import { generateText } from "ai";

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: "https://cloud.ratel.sh/v1/traces",
    headers: { Authorization: `Bearer ${process.env.RATEL_API_KEY}` },
  }),
});
sdk.start();

const { text } = await generateText({
  model,
  prompt: "Summarize the open tasks",
  experimental_telemetry: { isEnabled: true },
});

The AI SDK records prompts and tool calls by default. Cloud reads its ai.* attributes directly.

Any other emitter that follows the OpenTelemetry GenAI semantic conventions works the same way.

What Cloud reads

You getFromNeeds
Tokens, cost, model, latencygen_ai.usage.*, gen_ai.request.model, gen_ai.provider.nameNothing extra
Context breakdown: user input, history, tools, skills, memoryMessage contentContent capture on
Tool callsexecute_tool spans and tool-call messagesNothing extra
Unused toolsgen_ai.tool.definitionsYour instrumentation emitting the offered tools

Without content capture, totals stay exact and the breakdown counts everything as user input.

Content capture sends prompts and responses to Cloud. Turn it on only if that is acceptable for your data.

Check it works

Send one test span:

curl -s https://cloud.ratel.sh/v1/traces \
  -H "Authorization: Bearer $RATEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "resourceSpans": [{ "scopeSpans": [{ "spans": [{
        "traceId": "0123456789abcdef0123456789abcdef", "spanId": "0123456789abcdef",
        "name": "chat gpt-4o", "kind": 3,
        "startTimeUnixNano": "1751800000000000000", "endTimeUnixNano": "1751800001200000000",
        "attributes": [
          { "key": "gen_ai.operation.name", "value": { "stringValue": "chat" } },
          { "key": "gen_ai.provider.name", "value": { "stringValue": "openai" } },
          { "key": "gen_ai.request.model", "value": { "stringValue": "gpt-4o" } },
          { "key": "gen_ai.usage.input_tokens", "value": { "intValue": "1200" } },
          { "key": "gen_ai.usage.output_tokens", "value": { "intValue": "80" } }
        ] }] }] }] }'

A 202 with {"accepted":1,"calls":1,"spans":1} means Cloud stored it. The call then shows on your project's dashboard.

Limits and errors

  • Up to 4 MB per export.
  • LLM calls per month: Free 50,000, Plus 500,000, Pro 5,000,000, Enterprise unlimited.
StatusMeaning
202Accepted.
401Missing, invalid, or revoked API key.
413Export over 4 MB. Lower your batch size.
429Monthly call limit reached. Upgrade in Billing.

On this page