Skip to main content

Roda

Send traces to Levitate from a Roda app using OpenTelemetry

Introduction

Roda is a routing tree web toolkit for Ruby. This guide will help you set up OpenTelemetry instrumentation for your Roda application. You can also check out the example application on GitHub↗.

Pre-requisites

Before you begin, make sure you have:

  1. A Roda application set up and running.
  2. Signed up for Levitate and created a cluster.
  3. Obtained the following OTLP credentials from the Integrations page:
    • endpoint
    • auth_header

These credentials will be necessary for sending traces to your Levitate cluster.

Install OpenTelemetry Packages

To instrument your Roda application with OpenTelemetry, you need to install several gems. Add the following lines to your Gemfile:

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

Then, run the following command to install the packages:

bundle install

Set Environment Variables

Create a .env file in the root directory of your application and add the following environment variables:

OTEL_SERVICE_NAME=roda-api-service
OTEL_EXPORTER_OTLP_ENDPOINT=https://{endpoint}/v1/traces
OTEL_EXPORTER_OTLP_AUTH_HEADERS="Authorization=Basic {auth_header}"

Configure Roda Application

Add the following code to your Roda application to initialize OpenTelemetry in a new file instrumentation.rb:

# instrumentation.rb
require 'opentelemetry/sdk'
require 'opentelemetry/exporter/otlp'
require 'opentelemetry/instrumentation/all'

OpenTelemetry::SDK.configure do |c|
c.service_name = 'roda-api-service'
c.use_all('OpenTelemetry::Instrumentation::Rack' => {
url_quantization: -> (path, env) {
path_parts = path.to_s.split('/')
quantized_path = path_parts.map.with_index do |part, index|
if index > 0
case part
when /\A\d+\z/
":id" # Supports: /user/123 -> /user/:id
when /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i
":uuid" # Supports: /user/550e8400-e29b-41d4-a716-446655440000 -> /user/:uuid
else
part # Keeps other path parts unchanged: /api/v1/users -> /api/v1/users
end
else
part # Keeps the root path unchanged: / -> /
end
end.join('/')

# Examples of supported transformations for request path to span name:

# /user/123 -> /user/:id
# /api/v1/posts/abcd-1234-5678-efgh -> /api/v1/posts/:uuid
# /products/456/reviews/789 -> /products/:id/reviews/:id
# /categories/electronics/items/101 -> /categories/electronics/items/:id

"#{env['REQUEST_METHOD']} #{quantized_path}"
}
})
end

Update your entry file such as app.rb to load the instrumentation:

# app.rb

# Add following line to your Roda app
require 'rack'
require './instrumentation'

class App < Roda
# Your Roda app code here
end

# Add this line to your Roda app
App.use ::Rack::Events, [OpenTelemetry::Instrumentation::Rack::Middlewares::EventHandler.new]

Verify the setup

Start the Roda application and make some requests to it. You should see the application traces in your Levitate dashboard.

Troubleshooting

Please get in touch with us on Discord or Email if you have any questions.