Skip to main content

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

SignalStatusWhere it lives
LogsIn developmentSeparate 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


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 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-sdk gems, and the OTLP logs exporter gem is explicitly labelled experimental. The stable opentelemetry-sdk does 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_id and span_id, which is what enables trace-to-log pivots in CtrlB.
  • Bridge existing Logger calls. The opentelemetry-instrumentation-logger gem hooks Ruby's standard Logger class so existing logger.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 (filelog receiver) 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
Instrument all telemetry together

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.