# Roda

> Send traces to Last9 from a Roda app using OpenTelemetry

Source: https://last9.io/docs/integrations/frameworks/ruby/roda/

[Roda](https://roda.jeremyevans.net/) 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↗](https://github.com/last9/opentelemetry-examples/tree/master/ruby/roda).

## Pre-requisites

Before you begin, make sure you have:

1. A Roda application set up and running.
2. Signed up for [Last9](https://app.last9.io) and created a cluster.
3. Obtained the following OTLP credentials from the [Integrations](https://app.last9.io/integrations?integration=OpenTelemetry) page:
   - `endpoint`
   - `auth_header`

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

## Install OpenTelemetry Packages

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

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

Then, run the following command to install the packages:

```bash
bundle install
```

## Set Environment Variables

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

```bash
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`:

```ruby
# 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:

```ruby
# 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 Last9 dashboard.

---

## Running on Kubernetes

If you deploy your Roda app to Kubernetes, enrich traces with `k8s.*` semantic convention attributes (pod, namespace, node, deployment) using the Kubernetes Downward API. See [Kubernetes Resource Attributes](/docs/integrations/frameworks/ruby/kubernetes-resource-attributes/) for the deployment manifest.

## Troubleshooting

Please get in touch with us on [Discord](https://discord.com/invite/Q3p2EEucx9) or [Email](mailto:support@last9.io) if you have any questions.
