Ruby
| Traces | Metrics | App Logs | Custom Logs | Profiling | 
|---|---|---|---|---|
| ✅ | ✖ | ✖ | ✖ | ✅ | 
This guide walks you through instrumenting Ruby 3.0+ applications with Middleware APM in host-based and Heroku setups. It follows the same structure as your other language pages and keeps per-platform code blocks.
1. Prerequisites
- Middleware Host Agent running on the same machine (host-based mode). If your app is containerized, point it to the Host Agent via MW_AGENT_SERVICE:- Docker: 172.17.0.1
- Kubernetes: mw-service.mw-agent-ns.svc.cluster.local
 
- Docker: 
- Ruby 3.0+ Check using the following command:
1ruby --versionHeroku: If you deploy on Heroku, use the official Heroku buildpack for Middleware; it runs mw-agent inside the dyno and exposes local OTLP endpoints (HTTP 9320, gRPC 9313).
Supported frameworks: Rails, Sinatra, and generic Rack apps are covered via opentelemetry-instrumentation-all. No framework-specific code changes are required beyond the initialize step below.
Container networking tip: When the app runs inside a container on the same host as the Host Agent, use MW_AGENT_SERVICE=172.17.0.1 (Docker) or the in-cluster service DNS for Kubernetes so the app can reach the Host Agent on the host/cluster network.
2. Install
1 Add gems to your Gemfile
1gem 'opentelemetry-sdk'
2gem 'opentelemetry-exporter-otlp'
3gem 'opentelemetry-instrumentation-all'
4gem 'pyroscope'
5gem 'middleware_apm_linux', '~> 2.1.0'1gem 'opentelemetry-sdk'
2gem 'opentelemetry-exporter-otlp'
3gem 'opentelemetry-instrumentation-all'
4gem 'pyroscope'
5gem 'middleware_apm_windows', '~> 2.1.0'1gem 'opentelemetry-sdk'
2gem 'opentelemetry-exporter-otlp'
3gem 'opentelemetry-instrumentation-all'
4gem 'pyroscope'
5gem 'middleware_apm_linux', '~> 2.1.0'Then install:
1bundle installThe middleware_apm_* gems provide Middleware’s Ruby bootstrap plus profiling (via pyroscope). Latest published versions are listed on RubyGems.
2 Import & initialize the tracker at the very start of your app
1require 'middleware/ruby_gem_linux'
2Middleware::RubyGem.init1require 'middleware/ruby_gem_windows'
2Middleware::RubyGem.init1require 'middleware/ruby_gem_linux'
2Middleware::RubyGem.initFor Rails, you can add the require/init in config/environment.rb (before Rails.application.initialize!). Example:
1# config/environment.rb
2require_relative "application"
3require 'middleware/ruby_gem_linux'
4
5# Initialize Middleware.io application monitoring
6Middleware::RubyGem.init
7
8# Initialize the Rails application.
9Rails.application.initialize!3. Capture application data
1OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:9320 \
2    OTEL_SERVICE_NAME="<YOUR_SERVICE_NAME>" \
3    OTEL_RESOURCE_ATTRIBUTES=project.name="<YOUR_PROJECT_NAME>" \
4    MW_API_KEY="<MW_API_KEY>" \
5    <YOUR RUBY COMMAND>   # e.g., bundle exec puma -C config/puma.rb1$env:OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:9320"
2$env:OTEL_SERVICE_NAME="<YOUR_SERVICE_NAME>"
3$env:OTEL_RESOURCE_ATTRIBUTES='project.name="<YOUR_PROJECT_NAME>"'
4$env:MW_API_KEY="<MW_API_KEY>"
5ruby your_app.rb- The Middleware Heroku buildpack auto-configures the local OTLP endpoints and instrumentation. You typically don’t need to set OTEL_EXPORTER_OTLP_ENDPOINT.
- If you want to override service/project only, set:
1OTEL_SERVICE_NAME="<YOUR_SERVICE_NAME>"
2OTEL_RESOURCE_ATTRIBUTES='project.name=<YOUR_PROJECT_NAME>'(For Rails, you may set these envs in config/environment.rb before initializing the Middleware gem.)
4. Profiling
No extra steps required here. Profiling is auto-configured once you complete Step 2 (the pyroscope gem is part of the Gemfile set above).
5. View your data
After installation, wait 3–5 minutes, then open Middleware and check APM → Traces and Continuous Profiling. (Ruby does not currently expose app logs/custom logs in the Ruby guide.)
6. Environment variables
| Variable | Scope | Purpose | Example | 
|---|---|---|---|
| MW_AGENT_SERVICE | Host (containers) | Address/DNS of Host Agent (host-based installs) | 172.17.0.1 (Docker), mw-service.mw-agent-ns.svc.cluster.local (K8s) | 
| OTEL_EXPORTER_OTLP_ENDPOINT | All | Where to send OTLP (HTTP). Host-based default is the Host Agent at http://localhost:9320. Heroku buildpack sets this automatically. | http://localhost:9320 | 
| MW_API_KEY | All | Middleware API key (required for export). | xxxx… | 
| OTEL_SERVICE_NAME | All | Logical service name shown in APM. | orders-api | 
| OTEL_RESOURCE_ATTRIBUTES | All | Extra resource attrs; used for project scoping. | project.name=shop-app | 
| MW_TARGET | Heroku | Target ingest URL (set by the buildpack during setup). | https://<MW_UID>.middleware.io:443 | 
(Host-based vars and run commands: Ruby page; Heroku vars and behavior: Heroku buildpack page.)
7. Heroku buildpack quick setup (optional)
- From your Heroku app directory:1export APPNAME=<YOUR_HEROKU_APP>
- Enable dyno metadata (required for hostname continuity features):1heroku labs:enable runtime-dyno-metadata -a $APPNAME
- Add/open config:1heroku config:add MW_API_KEY=<MW_API_KEY> 2 heroku config:add MW_TARGET=https://<MW_UID>.middleware.io:443
Note: Ensure buildpack order: Middleware BEFORE your app buildpack The buildpack installs mw-agent into /app/mw-agent, starts it automatically, and exposes OTLP on ports 9313 (gRPC) and 9320 (HTTP).
8. Troubleshooting
- No data (host-based): Confirm that the Host Agent is running and that you have exported the MW_API_KEY. If running in Docker/K8s, ensureMW_AGENT_SERVICEpoints to the correct gateway/service and that you’re usinghttp://localhost:9320inside the same host/namespace.
- Rails not sending spans: Ensure require 'middleware/ruby_gem_*'andMiddleware::RubyGem.initrun beforeRails.application.initialize!.
- Heroku not wiring OTLP: Verify the buildpack is installed and ordered correctly (Middleware before your language buildpack), and that MW_API_KEYandMW_TARGETare set. Check dyno withheroku ps:execand inspect/app/mw-agent/mw-agent.log.
Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.