---
title: "Legacy OpenTelemetry Integration Support"
description: "Using OpenTelemetry with Sentry Performance."
url: https://docs.sentry.io/platforms/python/tracing/instrumentation/opentelemetry/
---

# Legacy OpenTelemetry Integration Support | Sentry for Python

##### New Integration Option

We now have a dedicated [OTLPIntegration](https://docs.sentry.io/platforms/python/integrations/otlp.md) that can directly ingest OpenTelemetry Traces into Sentry. We recommend moving over to the new setup since it is much simpler.

You can configure your [OpenTelemetry SDK](https://opentelemetry.io/) to send traces and spans to Sentry.

## [Install](https://docs.sentry.io/platforms/python/tracing/instrumentation/opentelemetry.md#install)

Sentry requires `opentelemetry-distro` version `0.350b0` or higher.

```bash
pip install "sentry-sdk[opentelemetry]"
```

## [Usage](https://docs.sentry.io/platforms/python/tracing/instrumentation/opentelemetry.md#usage)

Initialize Sentry for tracing and set the `instrumenter` to `otel`:

```python
import sentry_sdk

sentry_sdk.init(
    dsn="___PUBLIC_DSN___",
    # Add request headers and IP for users,
    # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
    send_default_pii=True,
    # Set traces_sample_rate to 1.0 to capture 100%
    # of transactions for tracing.
    traces_sample_rate=1.0,
    # Set the instrumenter to use OpenTelemetry instead of Sentry
    instrumenter="otel",
)
```

This disables all Sentry instrumentation and relies on the chosen OpenTelemetry tracers for creating spans.

Next, configure OpenTelemetry as you need and hook in the Sentry span processor and propagator. Here's a minimal example that doesn't require any additional OpenTelemetry setup:

```python
from opentelemetry import trace
from opentelemetry.propagate import set_global_textmap
from opentelemetry.sdk.trace import TracerProvider
from sentry_sdk.integrations.opentelemetry import SentrySpanProcessor, SentryPropagator

provider = TracerProvider()
provider.add_span_processor(SentrySpanProcessor())
trace.set_tracer_provider(provider)
set_global_textmap(SentryPropagator())
```

Finally, try it out with:

```python
import time

tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("test_otel_span"):
    print("Processing some data...")
    # Simulate some processing
    time.sleep(3)
```

## [OpenTelemetry and Sentry](https://docs.sentry.io/platforms/python/tracing/instrumentation/opentelemetry.md#opentelemetry-and-sentry)

With Sentry’s OpenTelemetry SDK, an OpenTelemetry `Span` becomes a Sentry `Transaction` or `Span`. The first `Span` sent through the Sentry `SpanProcessor` is a `Transaction`, and any child `Span` gets attached to the first `Transaction` upon checking the parent `Span` context. This is true for the OpenTelemetry root `Span` and any top level `Span` in the system. For example, a request sent from frontend to backend will create an OpenTelemetry root `Span` with a corresponding Sentry `Transaction`. The backend request will create a new Sentry `Transaction` for the OpenTelemetry `Span`. The Sentry `Transaction` and `Span` are linked as a trace for navigation and error tracking purposes.

## [Additional Configuration](https://docs.sentry.io/platforms/python/tracing/instrumentation/opentelemetry.md#additional-configuration)

If you need more fine-grained control over Sentry, take a look at the [Configuration page](https://docs.sentry.io/platforms/python/configuration.md). In case you'd like to apply client-side sampling or filter out transactions before sending them to Sentry (to get rid of health checks, for example), you may find the [Filtering page](https://docs.sentry.io/platforms/python/configuration/filtering.md#filtering-transaction-events) helpful.
