Skip to main content

Ruby

This guide walks you through setting up OpenTelemetry in your Ruby application and exporting metrics to CtrlB. The opentelemetry-instrumentation-all gem provides automatic instrumentation for 53+ popular Ruby libraries including Rails, Sinatra, Faraday, and more.

OpenTelemetry SDK status (mid-2026): Ruby metrics instrumentation is Development. See the OpenTelemetry language status table.

Signal stability in Ruby

SignalStatusWhere it lives
MetricsIn developmentSeparate opentelemetry-metrics-api / opentelemetry-metrics-sdk gems, pre-1.0; the maintainers describe the SDK as an alpha that does not yet implement the full specification.

This matters in practice. The stable opentelemetry-sdk gem does not bundle metrics — that signal is opt-in through its own gems, its APIs can change between minor releases, and you should pin exact versions if you adopt them. The OTLP metrics exporter also ships in its own gem, opentelemetry-exporter-otlp-metrics. If you need battle-tested metrics today and cannot accept a pre-1.0 dependency, a common interim path is to expose Prometheus (or StatsD) metrics and forward them into CtrlB with an OpenTelemetry Collector.

Prerequisites


Step 1. Install Dependencies

You can install OpenTelemetry in two main ways—depending on whether you want all instrumentations or just specific ones.

Add the OpenTelemetry SDK, OTLP exporter, and the metapackage that includes all instrumentation libraries to your Gemfile:

gem 'opentelemetry-sdk'
gem 'opentelemetry-exporter-otlp'
gem 'opentelemetry-instrumentation-all'

If you prefer to install only specific instrumentation, add the specific instrumentation libraries to your Gemfile:

gem 'opentelemetry-sdk'
gem 'opentelemetry-exporter-otlp'
gem 'opentelemetry-instrumentation-sinatra'
gem 'opentelemetry-instrumentation-faraday'
# Add other specific instrumentations as needed

Install gems added to the Gemfile

bundle install

Step 2. Configure OpenTelemetry Instrumentation

Once dependencies are installed, you can configure OpenTelemetry in your application. You can write the configuration in a Rails initializer file like config/initializers/opentelemetry.rb.

A. Configure all instrumentation libraries

If you installed opentelemetry-instrumentation-all, you can enable all instrumentations easily.

Example (Rails initializer):

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

OpenTelemetry::SDK.configure do |c|
c.service_name = '<YOUR_SERVICE_NAME>'
c.use_all # enables all instrumentation
end

This automatically enables all supported libraries detected in your app.


B. Override configuration for specific libraries

If you want to disable or modify specific instrumentations while using use_all, you can provide a configuration map.

Example: Disable Redis instrumentation

require 'opentelemetry/sdk'
require 'opentelemetry/instrumentation/all'

OpenTelemetry::SDK.configure do |c|
config = { 'OpenTelemetry::Instrumentation::Redis' => { enabled: false } }
c.use_all(config)
end

To override multiple libraries, add more entries to the config hash.


C. Configure specific instrumentation libraries only

If you prefer to use only certain instrumentations, explicitly enable them:

require 'opentelemetry/sdk'

OpenTelemetry::SDK.configure do |c|
c.use 'OpenTelemetry::Instrumentation::Sinatra'
c.use 'OpenTelemetry::Instrumentation::Faraday', { opt: 'value' }
end

Use this approach for production deployments where you want tight control over instrumentation. To explore the full range of Ruby instrumentation options, refer to the following resources:


Emit metrics with the OpenTelemetry SDK

To record application metrics — counters, histograms, and gauges — you opt into the separate metrics gems and create instruments in your code. This exports real OTLP metrics to CtrlB.

Heads up — metrics are in development in Ruby. The metrics signal ships as the pre-1.0 opentelemetry-metrics-api / opentelemetry-metrics-sdk gems, which the maintainers describe as an alpha that does not yet implement the full Metrics SDK specification. The OTLP metrics exporter lives in its own gem, opentelemetry-exporter-otlp-metrics. It works today, but APIs may change between releases — pin exact versions and treat upgrades as reviewable changes.

Add the metrics SDK and OTLP metrics exporter to your Gemfile:

gem 'opentelemetry-metrics-sdk'
gem 'opentelemetry-exporter-otlp-metrics'

Then install:

bundle install

Configure the SDK, then explicitly wire an OTLP metric reader onto the global meter provider — unlike traces, OpenTelemetry::SDK.configure does not attach a metrics exporter for you in this alpha gem. The exporter honors the same OTLP environment variables as the other signals (see Step 3), so no endpoint or auth is hard-coded here:

require 'opentelemetry/sdk'
require 'opentelemetry-metrics-sdk'
require 'opentelemetry-exporter-otlp-metrics'

OpenTelemetry::SDK.configure do |c|
c.service_name = '<YOUR_SERVICE_NAME>'
end

otlp_metrics = OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new
reader = OpenTelemetry::SDK::Metrics::Export::PeriodicMetricReader.new(
export_interval_millis: 15_000,
export_timeout_millis: 10_000,
exporter: otlp_metrics
)
OpenTelemetry.meter_provider.add_metric_reader(reader)

# Create instruments once, record from anywhere.
meter = OpenTelemetry.meter_provider.meter('<YOUR_SERVICE_NAME>')

orders = meter.create_counter(
'orders.processed',
unit: '{order}',
description: 'Number of orders processed'
)
latency = meter.create_histogram(
'payment.duration',
unit: 'ms',
description: 'Payment processing duration'
)

started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# ... process a payment ...
orders.add(1, attributes: { 'payment.provider' => 'stripe' })
elapsed_ms = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - started) * 1000
latency.record(elapsed_ms)

# Flush and stop the reader before exit.
OpenTelemetry.meter_provider.shutdown

What you should not expect yet: full parity with the stable SDKs — some view/aggregation features and parts of the configuration surface are incomplete (exemplars, by contrast, are supported via the AlwaysOnExemplarFilter, AlwaysOffExemplarFilter, and the default TraceBasedExemplarFilter).

Interim alternative. If you need battle-tested Ruby metrics today and cannot accept a pre-1.0 dependency, expose Prometheus metrics (or StatsD) and scrape/forward them into CtrlB with an OpenTelemetry Collector, keeping OTel traces alongside.


Step 3. Configure Exporter for CtrlB

Once your application is instrumented, configure the OTLP exporter to send telemetry data directly to CtrlB.

Set the following environment variables before starting your app:

OTEL_EXPORTER=otlp \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
OTEL_SERVICE_NAME=<service_name> \
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://<INGESTION_HOST>/api/default/v1/metrics \
OTEL_TRACES_EXPORTER=none \
OTEL_LOGS_EXPORTER=none \
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <API_TOKEN>,stream-name=<STREAM_NAME>" \
rails server
Instrument all telemetry together

The block above sends metrics only. To export traces, metrics, and logs from the same application, use the shared OTLP endpoint and headers instead of the signal-specific endpoint above:

OTEL_EXPORTER_OTLP_ENDPOINT=https://<INGESTION_HOST>/api/default \
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://<INGESTION_HOST>/api/default/<STREAM_NAME>/_otel/v1/logs \
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <API_TOKEN>,stream-name=<STREAM_NAME>"

Step 4. Use OpenTelemetry Collector (Optional)

For production setups, it’s recommended to send metrics through an OpenTelemetry Collector before CtrlB. This enables buffering, batching, retries, and multi-sink routing.

See OpenTelemetry for Metrics for configuration details.