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
| Signal | Status | Where it lives |
|---|---|---|
| Metrics | In development | Separate 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
- Ruby 3.2+
- Bundler
- CtrlB OTLP (ingestion host, auth, stream, service name): See Prerequisites
Step 1. Install Dependencies
You can install OpenTelemetry in two main ways—depending on whether you want all instrumentations or just specific ones.
A: Install all instrumentation libraries (recommended for getting started)
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'
B: Install specific instrumentation libraries (recommended for production)
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-sdkgems, 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
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.