---
title: Ruby Observability with OpenTelemetry | Pydantic Logfire
description: >-
  Send Ruby and Rails traces to Pydantic Logfire with the standard OpenTelemetry
  Ruby SDK, then query traces, metrics, and logs with SQL.
canonical: 'https://pydantic.dev/logfire/ruby'
---

> Markdown version of [Trace, monitor and debug your Ruby app](https://pydantic.dev/logfire/ruby) — the canonical HTML page.
>
> Site index: [/llms.txt](https://pydantic.dev/llms.txt)

---

# Trace, monitor and debug your Ruby app

Logfire for Ruby

Ruby Observability from the team behind Pydantic: trace Rails and Ruby apps, capture requests, queries and outbound calls, and query everything in plain SQL. Standard OpenTelemetry, no lock-in.

[Try Logfire for free](https://logfire.pydantic.dev/login?intent=signup) [See the Ruby docs](https://pydantic.dev/docs/logfire/instrument/ruby/)

Set up Logfire with your coding agent:

uvx logfire-cli wizard

Install and configure

```bash
gem install opentelemetry-sdk opentelemetry-exporter-otlp opentelemetry-instrumentation-all
```

Configure exporter

```bash
export OTEL_EXPORTER_OTLP_ENDPOINT='https://logfire-us.pydantic.dev'
export OTEL_EXPORTER_OTLP_HEADERS='Authorization=your-write-token'
```

Instrument your app

View code

```ruby
require 'opentelemetry/sdk'
require 'opentelemetry/exporter/otlp'
require 'opentelemetry/instrumentation/all'

OpenTelemetry::SDK.configure do |c|
  c.service_name = 'hello-ruby'
  # Without use_all you get only the spans you write yourself.
  c.use_all
end

tracer = OpenTelemetry.tracer_provider.tracer('hello-ruby')

tracer.in_span('Hello World') do |span|
  # your work here
end

# No at_exit hook in the Ruby SDK: flush before the process exits.
OpenTelemetry.tracer_provider.shutdown
```

Full details are in the [Ruby setup guide](https://pydantic.dev/docs/logfire/instrument/ruby/).

Trusted by teams building production software and AI

**Customers:** Motorola, Sophos, Airbyte, Pictet, Vox Media, Weaviate, Amboss, Tiger Data

What you get

## One request, one trace

![A Logfire trace of a Ruby request: the service's own spans, PG queries and the outbound Net::HTTP call, with an errored request below](https://pydantic.dev/assets/logfire/language-traces/ruby-trace.png)

**What lands in Logfire:**

* your `in_span` blocks, nested as they ran
* each `ActiveRecord`/PG query, timed
* the outbound `Net::HTTP` call
* an error recorded on the span that raised, not just at the top

Try it on your stack

## See your own Ruby trace

Start free with 10 million spans, logs, and metrics each month. No credit card required.

[Start free](https://logfire.pydantic.dev/login?intent=signup) [Read the Ruby setup guide](https://pydantic.dev/docs/logfire/instrument/ruby/)

How it works

## Standard OpenTelemetry, hosted backend

### Rails and Rack instrumented for you

The OpenTelemetry Ruby contrib gems cover Rails and Rack, along with common database and HTTP libraries such as ActiveRecord, Sidekiq, Net::HTTP, Faraday, Redis, and PostgreSQL. Incoming requests become traces without instrumenting each call site, and your own spans nest inside them.

### Blocks, not manual start and finish

tracer.in\_span('...') do |span| closes the span even if the block raises, so an exception is recorded on the span rather than the span being lost. The failure case is the one you most want telemetry for, so the safe form is also the idiomatic one.

### Standard OTLP, so genuinely no lock-in

Configuration is OTEL\_ environment variables against the standard OpenTelemetry Ruby SDK. Your Gemfile contains OpenTelemetry gems and nothing of ours, so repointing at a different backend is a config change rather than a migration.

### Traces now, metrics and logs as Ruby's SDKs land

Logfire ingests traces, metrics, and logs in one project, and the setup above sends traces with the stable OpenTelemetry Ruby SDK. Ruby's metrics and logs SDKs are still pre-1.0 (opentelemetry-metrics-sdk and opentelemetry-logs-sdk), and the OTLP logs exporter still ships as experimental, so treat those as available but early rather than a finished path. Traces are the part that is production-ready today, and everything you send is queryable with the same SQL.

### SQL instead of a query language you have to learn

Use PostgreSQL-compatible SQL to compare Rails routes, Sidekiq jobs, database spans, and any attributes your instrumentation records. Save the result as a dashboard or alert without translating the question into a vendor-specific language.

Query

## Query your Ruby telemetry with SQL

If you can ask it, SQL can find out

* Query your traces, metrics and logs with real SQL
* No proprietary query language to learn
* AI models are great at writing SQL
* From a one-off investigation to an alert, dashboard, or SLO

```sql
select
  attributes->>'http.route' as route,
  count(*) as requests,
  avg(duration) as avg_seconds
from records
where duration > 1
group by route
order by avg_seconds desc;
```

Proof

## In production

> You can tell that Pydantic Logfire was built by people who use it.

Dennis Griffin, VP of Engineering, Sophos [Read the case study](https://pydantic.dev/case-studies/sophos)

Decision guide

## Is Logfire right for you?

### Choose Logfire if

* You run Rails or Rack and want request traces without a proprietary agent
* You want only OpenTelemetry gems in your Gemfile
* You want to query traces, metrics, and logs with PostgreSQL-compatible SQL
* You do not want to run Jaeger, Prometheus, and storage yourself
* You want the option to repoint at another backend without a rewrite

### Choose a vendor APM if

* You want a vendor-maintained Ruby SDK with vendor-specific APIs
* You are already deeply integrated with a specific APM vendor's ecosystem
* You need a vendor-only integration or compliance capability Logfire does not offer

FAQ

## Common questions

### Is there a Logfire SDK for Ruby?

No. Ruby uses the standard OpenTelemetry Ruby SDK, and Logfire is the OTLP backend it exports to, so nothing proprietary enters your Gemfile. First-party Logfire SDKs exist for Python, TypeScript, and Rust.

### Does this work with Rails?

Yes. The OpenTelemetry Ruby contrib instrumentation gems cover Rails and Rack, so incoming requests become spans automatically, with ActiveRecord queries and outbound HTTP calls attached as child spans. Your own in\_span blocks then nest inside the request span.

### Why is nothing arriving in Logfire?

Check that both gems are installed, opentelemetry-sdk and opentelemetry-exporter-otlp, that the endpoint matches your project's data region, and that the Authorization header carries a valid write token. Short-lived scripts also need the exporter to flush before the process exits.

### Why use in\_span rather than manual start and finish?

The block form closes the span even when the block raises, so an exception is recorded on the span instead of the span being lost entirely. That is exactly the case you most want telemetry for, so the block form is the safer default.

### Am I locked in to Logfire?

No. Configuration is standard OTEL\_ environment variables against the standard SDK, and your code references OpenTelemetry types only. Repoint the endpoint at another OpenTelemetry-compatible backend, or at your own collector, whenever you want.

## Start seeing your Ruby app

Get started with 10 million free spans, logs, and metrics per month. No credit card required.

* [Start free](https://logfire.pydantic.dev/login?intent=signup)
* [Book a demo](https://pydantic.dev/contact)
* [View pricing plans](https://pydantic.dev/pricing)
