Ruby
This guide walks you through setting up OpenTelemetry in your Ruby application and exporting logs 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 log instrumentation is Development. See the OpenTelemetry language status table.
Signal stability in Ruby
| Signal | Status | Where it lives |
|---|---|---|
| Logs | In development | Separate opentelemetry-logs-api / opentelemetry-logs-sdk gems, pre-1.0; the OTLP logs exporter gem is explicitly labelled experimental. |
This matters in practice. The stable opentelemetry-sdk gem does not bundle logs — the signal is opt-in through its own gems, its API can change between minor releases, and you should pin exact versions if you adopt it. For teams that want to stay conservative, a common alternative is a sidecar path such as JSON logs scraped by 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 logs with the OpenTelemetry SDK
The instrumentation above wires up request context that your log records can be correlated against. To emit log records through OpenTelemetry, you opt into the separate logs gems and record logs from your application code. This ships those logs to CtrlB over OTLP.
Heads up — logs are experimental in Ruby. The logs signal lives in the pre-1.0
opentelemetry-logs-api/opentelemetry-logs-sdkgems, and the OTLP logs exporter gem is explicitly labelled experimental. The stableopentelemetry-sdkdoes not bundle them. Pin exact versions and treat upgrades as reviewable changes.
Add the logs SDK and OTLP logs exporter to your Gemfile:
gem 'opentelemetry-logs-sdk'
gem 'opentelemetry-exporter-otlp-logs'
Then install:
bundle install
Configure the SDK, then explicitly wire an OTLP log record processor onto the global logger provider — unlike traces, OpenTelemetry::SDK.configure does not attach a logs exporter for you. The exporter reads the standard environment variables in Step 3, so no endpoint or auth is hard-coded here:
require 'opentelemetry/sdk'
require 'opentelemetry-logs-sdk'
require 'opentelemetry-exporter-otlp-logs'
OpenTelemetry::SDK.configure do |c|
c.service_name = '<YOUR_SERVICE_NAME>'
end
OpenTelemetry.logger_provider.add_log_record_processor(
OpenTelemetry::SDK::Logs::Export::BatchLogRecordProcessor.new(
OpenTelemetry::Exporter::OTLP::Logs::LogsExporter.new
)
)
otel_logger = OpenTelemetry.logger_provider.logger(name: '<YOUR_SERVICE_NAME>')
otel_logger.on_emit(
timestamp: Time.now,
severity_text: 'INFO',
body: 'order processed',
attributes: { 'order.id' => 'ord_8412', 'amount.cents' => 4599 }
)
# Flush buffered records before the process exits — critical for scripts,
# rake tasks, and cron jobs.
OpenTelemetry.logger_provider.shutdown
A few points that matter:
- Trace correlation is automatic. Records emitted while a span is active are exported with that span's
trace_idandspan_id, which is what enables trace-to-log pivots in CtrlB. - Bridge existing
Loggercalls. Theopentelemetry-instrumentation-loggergem hooks Ruby's standardLoggerclass so existinglogger.info(...)calls flow into the OTel logs pipeline without rewriting call sites — the same experimental caveats apply.
Interim alternative. Because this signal is the least mature, many production teams skip the in-process logs SDK entirely: write structured JSON logs to stdout, collect them with an OpenTelemetry Collector (
filelogreceiver) or FluentBit, and forward to CtrlB. Include the current trace ID in each line (OpenTelemetry::Trace.current_span.context.hex_trace_id) to keep correlation without the pre-1.0 dependency. Both paths land in the same CtrlB log streams — pick based on your risk tolerance.
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_LOGS_ENDPOINT=https://<INGESTION_HOST>/api/default/<STREAM_NAME>/_otel/v1/logs \
OTEL_TRACES_EXPORTER=none \
OTEL_METRICS_EXPORTER=none \
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic <API_TOKEN>,stream-name=<STREAM_NAME>" \
rails server
The block above sends logs 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 logs through an OpenTelemetry Collector before CtrlB. This enables buffering, batching, retries, and multi-sink routing.
See OpenTelemetry Collector for Logs for configuration details.