skip to content

How do you make OpenLLMetry send traces to your own backend instead of Traceloop's cloud?

level: middleimportance: should knowfreq 44%

answer

  1. destination is a parameter, not a lock-in
  2. exporter= takes any OTel span exporter
  3. api_endpoint / TRACELOOP_BASE_URL retarget the default
  4. console exporter answers 'is anything produced?'
  5. collector first, vendor second

basics

~20 s

Pass an OpenTelemetry span exporter to Traceloop.init(exporter=...), or point the SDK at your own OTLP endpoint with the api_endpoint and headers arguments or the TRACELOOP_BASE_URL and TRACELOOP_HEADERS environment variables. LLM spans then land in whatever backend already receives your traces.

solid answer

~40 s

`Traceloop.init()` defaults to shipping spans to Traceloop's hosted endpoint using a `TRACELOOP_API_KEY`, but that is a default, not a lock-in — the SDK is OpenTelemetry underneath. Two routes exist. The declarative one: set `api_endpoint`/`headers` on `init` (or `TRACELOOP_BASE_URL`/`TRACELOOP_HEADERS` in the environment) so the built-in OTLP exporter targets your collector or an OTLP-compatible vendor. The programmatic one: build any OTel `SpanExporter` yourself and pass it as `exporter=`, which overrides the destination entirely — an `OTLPSpanExporter` aimed at `http://otel-collector:4318/v1/traces`, or a `ConsoleSpanExporter` when you just want to see spans locally. The usual production shape is exporting to your own collector so LLM spans sit in the same trace as HTTP and database spans, with routing and redaction handled in one place.

code

python · 9 lines
python
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from traceloop.sdk import Traceloop

Traceloop.init(
    app_name="chat-api",
    exporter=OTLPSpanExporter(
        endpoint="http://otel-collector:4318/v1/traces",
    ),
)

go deeper

for a junior

Know that Traceloop.init() takes an exporter argument and endpoint settings, and that a console exporter is the quick way to see spans while developing.

for a middle

Explain both routes — retarget the built-in OTLP exporter with api_endpoint/headers or environment variables, or pass your own exporter object — and why environment configuration suits deployments better than code.

for a senior

Argue for exporting to a collector you operate: one trace containing HTTP, database and LLM spans, central redaction of prompt content, and vendor changes without redeploying services. Be able to bisect a silent export failure.

for a principal

Own it as policy: services export to a local collector, the collector owns routing, redaction and sampling, and no team hardcodes a vendor destination. That keeps prompt content inside the network boundary and makes backend migration a config change.

## Destination is a parameter, not a lock-in The most common misconception about OpenLLMetry is that adopting it means adopting Traceloop's SaaS. It does not. The SDK is a packaging of OpenTelemetry instrumentation for LLM libraries, and the exporter — the component that decides where finished spans go — is configurable at `init`. ## Route one: point the built-in exporter elsewhere Out of the box the SDK builds an OTLP exporter. You can retarget it without writing exporter code: - `Traceloop.init(app_name="chat-api", api_endpoint="http://otel-collector:4318", headers={"x-tenant": "eu"})` - or the environment equivalents `TRACELOOP_BASE_URL` and `TRACELOOP_HEADERS`, with `TRACELOOP_API_KEY` for the hosted endpoint. Environment variables are usually the better production choice, because destination is a deployment concern: the same image runs against a local collector in dev and a gateway collector in prod, with no code change and no per-environment branch in your startup path. ## Route two: pass your own exporter object `init` takes an `exporter` argument that accepts any OpenTelemetry span exporter instance. This wins when you need something the endpoint settings cannot express: - an exporter with custom transport, retry or credential behaviour; - a vendor's own exporter implementation; - `ConsoleSpanExporter` for local debugging, which prints each finished span to stdout and answers "is anything being produced at all?" faster than any dashboard; - an in-memory exporter in tests, so a test can assert that a workflow span was emitted with the attributes you expect. When you pass `exporter`, it is the destination — the endpoint settings no longer apply. ## Why teams route to their own collector Sending to a collector you run, rather than straight to a vendor, is the mainstream production pattern for reasons that have little to do with OpenLLMetry specifically: 1. **One trace, one place.** If your web framework and database clients are already OTel-instrumented, the LLM span joins the request's existing trace. "This endpoint got slow" and "this model call got slow" become the same investigation instead of two tools and a timestamp correlation. 2. **Redaction at the boundary.** Prompt and completion text is captured by default, and a collector is a natural chokepoint to scrub or drop attributes before they leave your network. That is a stronger control than trusting every service to configure itself correctly. 3. **Vendor portability.** Changing backends becomes a collector config change rather than a redeploy of every service. 4. **Egress and cost shaping.** Sampling, filtering and batching happen once, centrally, on data that has already left the request path. The detailed design of that collector — receivers, processors, tail sampling, gateway topology — is a separate OpenTelemetry subject; from OpenLLMetry's side the whole integration is "which endpoint, which headers". ## Debugging destination problems When spans do not arrive, split the question in two: *are spans being produced* and *are they arriving*. Swap in a console exporter and rerun; if you see spans in stdout, instrumentation is working and the problem is endpoint, credentials, network or the backend. If you see nothing, the problem is upstream — instrumentation not applied, calls made before `init`, or a process exiting before export. Two destination-specific traps are worth remembering. First, the path and port conventions differ between OTLP over HTTP and OTLP over gRPC, and a wrong endpoint typically fails quietly in the exporter's own logs rather than raising in your application — telemetry systems are built not to take the app down. Second, authentication headers for a vendor backend belong in `headers`/`TRACELOOP_HEADERS`; a missing header usually surfaces as rejected exports on the receiving side rather than as an error you notice locally. ## Interview framing If asked "does using OpenLLMetry mean sending our prompts to a third party?", the strong answer is: no, the destination is `init`'s exporter or endpoint configuration, the common shape is exporting to a collector we run, and content capture is separately controllable. That answer demonstrates you understand OpenLLMetry as an instrumentation library rather than a SaaS client.

  • Would you set the endpoint in code or in the environment?
    Environment, in almost every case. Destination is a deployment property, so TRACELOOP_BASE_URL and TRACELOOP_HEADERS let one image run against a local collector in development and a gateway in production with no code branch. Reserve the exporter argument for cases the settings cannot express, such as an in-memory exporter in tests or a vendor-specific exporter implementation.
  • An interviewer asks whether adopting OpenLLMetry means prompts leave your network. What do you say?
    Not necessarily. The SDK is OpenTelemetry instrumentation; the hosted endpoint is only the default destination. Point the exporter at a collector you run and the spans never reach a third party, and content capture is separately controllable if you must not record prompt text at all. The collector is also the right place to redact attributes centrally rather than per service.
  • You point OpenLLMetry at a collector, restart, and see nothing in the backend while the app runs fine. How do you narrow it down?
    Swap in a console exporter and rerun. Spans in stdout mean production is fine and the fault is downstream — wrong endpoint scheme, port or path, missing auth headers, or the collector dropping data. No spans in stdout moves the investigation upstream to instrumentation or process lifetime. Exporters fail quietly by design, so check the SDK's own logs rather than expecting an application error.

saying these in an interview costs you the question

  • Believing OpenLLMetry requires sending data to Traceloop's cloud
  • Hardcoding a production endpoint in application code
  • Expecting a bad endpoint to raise an exception in your app
  • Passing both an exporter and endpoint settings and expecting both to apply
  • Skipping the collector and exporting from every service straight to a vendor

context