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

# Legacy OpenTelemetry Support | Sentry for Rails

##### New Integration Option

We now have a dedicated [OTLP Integration](https://docs.sentry.io/platforms/ruby/guides/rails/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/ruby/guides/rails/tracing/instrumentation/opentelemetry.md#install)

The `sentry-opentelemetry` gem requires `opentelemetry-sdk` `1.0.0` or higher.

```ruby
gem "sentry-ruby"
gem "sentry-rails"
gem "sentry-opentelemetry"

gem "opentelemetry-sdk"
gem "opentelemetry-instrumentation-all"
```

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

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

`config/initializers/sentry.rb`

```ruby
Sentry.init do |config|
  config.dsn = "___PUBLIC_DSN___"
  config.traces_sample_rate = 1.0
  # set the instrumenter to use OpenTelemetry instead of Sentry
  config.instrumenter = :otel
end
```

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:

`config/initializers/otel.rb`

```ruby
OpenTelemetry::SDK.configure do |c|
  c.use_all
  c.add_span_processor(Sentry::OpenTelemetry::SpanProcessor.instance)
end

OpenTelemetry.propagation = Sentry::OpenTelemetry::Propagator.new
```

Note that if you are using the Ruby OpenTelemetry gem [*pre-v0.24.0*](https://github.com/open-telemetry/opentelemetry-ruby-contrib/tree/main/instrumentation/rack#rack-middleware-vs-rack-events) along with extra Sentry features such as tags / user, you will need to re-order the middleware as below to make sure Sentry's scope management works properly. (After v0.24.0, the gem [uses Rack Events rather than a middleware.](https://github.com/open-telemetry/opentelemetry-ruby-contrib/tree/main/instrumentation/rack#rack-middleware-vs-rack-events))

`config/initializers/otel.rb`

```ruby
Rails.application.config.middleware.move_after(
  Sentry::Rails::CaptureExceptions,
  OpenTelemetry::Instrumentation::Rack::Middlewares::TracerMiddleware
)
```

## [OpenTelemetry and Sentry](https://docs.sentry.io/platforms/ruby/guides/rails/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/ruby/guides/rails/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/ruby/guides/rails/configuration.md). In case you'd like to 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/ruby/guides/rails/configuration/filtering.md#filtering-transaction-events) helpful.
