> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squasher.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Ruby & Rails

> Send errors and logs from Ruby and Rails applications to Squasher.

## Recommended: OpenTelemetry SDK

Auto-instrument Rails, Sinatra, and other Rack-based frameworks.

### 1. Install

```bash theme={null}
gem install opentelemetry-sdk \
  opentelemetry-exporter-otlp \
  opentelemetry-instrumentation-all
```

Or add to your `Gemfile`:

```ruby theme={null}
gem "opentelemetry-sdk"
gem "opentelemetry-exporter-otlp"
gem "opentelemetry-instrumentation-all"
```

### 2. Configure

Create an initializer `config/initializers/opentelemetry.rb`:

```ruby theme={null}
require "opentelemetry/sdk"
require "opentelemetry/exporter/otlp"
require "opentelemetry/instrumentation/all"

OpenTelemetry::SDK.configure do |c|
  c.service_name = "my-rails-app"
  c.use_all # Auto-instrument Rails, ActiveRecord, Net::HTTP, etc.
end
```

### 3. Set Environment Variables

```bash theme={null}
export OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.squasher.ai
export OTEL_EXPORTER_OTLP_HEADERS="x-squasher-key=sq_pk_your_api_key"
export OTEL_SERVICE_NAME=my-rails-app
```

### 4. Run

```bash theme={null}
rails server
```

All exceptions raised in controllers, jobs, and middleware are automatically captured.

## Rails Error Reporting (Rails 7.1+)

Rails 7.1 introduced `Rails.error.handle` and `Rails.error.report`. You can hook Squasher into this with a custom subscriber using the HTTP API:

```ruby theme={null}
# config/initializers/squasher.rb
class SquasherErrorSubscriber
  ENDPOINT = "https://ingest.squasher.ai/v1/ingest/#{ENV['SQUASHER_PROJECT_ID']}"

  def report(error, handled:, severity:, context: {}, source: nil)
    Net::HTTP.post(
      URI(ENDPOINT),
      {
        message: error.message,
        type: error.class.name,
        level: severity.to_s == "error" ? "error" : "warning",
        stack: error.backtrace&.join("\n"),
        environment: Rails.env,
        tags: context.transform_values(&:to_s),
      }.to_json,
      "Content-Type" => "application/json",
      "x-squasher-key" => ENV["SQUASHER_API_KEY"],
    )
  rescue StandardError
    # Don't let reporting failures crash the app
  end
end

Rails.error.subscribe(SquasherErrorSubscriber.new)
```

## Alternative: Direct HTTP API

```ruby theme={null}
require "net/http"
require "json"

module Squasher
  ENDPOINT = URI("https://ingest.squasher.ai/v1/ingest/#{ENV['SQUASHER_PROJECT_ID']}")
  API_KEY = ENV["SQUASHER_API_KEY"]

  def self.capture_error(error, tags: {})
    payload = {
      message: error.message,
      type: error.class.name,
      level: "error",
      stack: error.backtrace&.join("\n"),
      environment: ENV.fetch("RAILS_ENV", "production"),
      tags: tags.transform_values(&:to_s),
    }

    Thread.new do
      req = Net::HTTP::Post.new(ENDPOINT)
      req["Content-Type"] = "application/json"
      req["x-squasher-key"] = API_KEY
      req.body = payload.to_json
      Net::HTTP.start(ENDPOINT.hostname, ENDPOINT.port, use_ssl: true) do |http|
        http.request(req)
      end
    rescue StandardError
      # Silently fail
    end
  end

  def self.log(level, message, tags: {})
    payload = {
      message: message,
      level: level.to_s,
      tags: tags.transform_values(&:to_s),
    }

    Thread.new do
      req = Net::HTTP::Post.new(ENDPOINT)
      req["Content-Type"] = "application/json"
      req["x-squasher-key"] = API_KEY
      req.body = payload.to_json
      Net::HTTP.start(ENDPOINT.hostname, ENDPOINT.port, use_ssl: true) do |http|
        http.request(req)
      end
    rescue StandardError
      # Silently fail
    end
  end
end
```

### Usage

```ruby theme={null}
begin
  process_payment(order)
rescue => e
  Squasher.capture_error(e, tags: { order_id: order.id, amount: order.total })
  raise
end

Squasher.log(:info, "Deployment completed", tags: { version: "v1.2.3" })
```

## Sinatra

Same OTel setup works with Sinatra:

```bash theme={null}
gem install opentelemetry-instrumentation-sinatra
```

```ruby theme={null}
require "opentelemetry/instrumentation/sinatra"

OpenTelemetry::SDK.configure do |c|
  c.use "OpenTelemetry::Instrumentation::Sinatra"
end
```

## Agent handoff

```text theme={null}
For Ruby or Rails, prefer OpenTelemetry auto-instrumentation first. Use direct HTTP only for small custom hooks, keep keys in env, verify one Rails.error or exception path, and flush any queued work before shutdown when applicable.
```
