OpenTelemetry Python SDK
Using the OpenTelemetry Python SDK
This guide shows you how to directly instrument your Python applications with the OpenTelemetry SDK to send trace data to Opik.
Installation
First, install the required OpenTelemetry packages:
Full Example
Here’s a complete example that demonstrates how to instrument a chatbot application with OpenTelemetry and send the traces to Opik:
Using thread_id as a span attribute allows you to group related spans into a single conversational thread.
Created threads can be used to evaluate multi-turn conversations as described in the Multi-turn conversations guide.
Linking OpenTelemetry spans to an existing Opik trace
If a service instrumented with OpenTelemetry is invoked by another service that is already producing an Opik trace (via the Opik SDK or @track), you can link the OpenTelemetry spans to the existing Opik trace and parent span by propagating two HTTP headers (opik_trace_id, opik_parent_span_id) and calling the Opik bridging helper on the receiving side. The helper sets the opik.trace_id / opik.parent_span_id attributes on the OpenTelemetry boundary span so the Opik OTLP ingest endpoint attaches the span to the right parent.
Recommended setup: register OpikSpanProcessor
distributed_trace.attach_to_parent only sets the Opik attributes on the boundary span. Children created inside that span via start_as_current_span inherit OTel context but not those attributes — without extra wiring they end up orphaned in a synthetic Opik trace. Register OpikSpanProcessor on the same TracerProvider as your OTLP exporter to propagate the Opik IDs down the entire attached subtree:
The processor only mutates spans whose parent already carries Opik attributes (set by attach_to_parent on the boundary, or inherited from upstream W3C baggage). Spans outside an attached subtree are left untouched.
For the full client/server pattern with Python and TypeScript examples, see Distributed Traces with a Remote Service Using OpenTelemetry.