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

# Rack

export const Compatibility = ({versions = [], label = "Available in"}) => {
  if (!Array.isArray(versions) || versions.length === 0) {
    return null;
  }
  const defaultPillStyle = {
    borderColor: "#d4d4d8",
    background: "#f4f4f5",
    color: "#3f3f46"
  };
  const pillStyles = {
    "AppSignal for Elixir": {
      background: "#f3e8ff",
      borderColor: "#d8b4fe",
      color: "#6b21a8"
    },
    "AppSignal for Front-end": {
      background: "#fef9c3",
      borderColor: "#fde047",
      color: "#854d0e"
    },
    "AppSignal for Go": {
      background: "#ccfbf1",
      borderColor: "#5eead4",
      color: "#115e59"
    },
    "AppSignal for JavaScript": {
      background: "#fef9c3",
      borderColor: "#fde047",
      color: "#854d0e"
    },
    "AppSignal for Node.js": {
      background: "#dcfce7",
      borderColor: "#86efac",
      color: "#166534"
    },
    "AppSignal for Python": {
      background: "#dbeafe",
      borderColor: "#93c5fd",
      color: "#1e40af"
    },
    "AppSignal for Ruby": {
      background: "#fee2e2",
      borderColor: "#fca5a5",
      color: "#991b1b"
    },
    "AppSignal for Rust": {
      background: "#ffedd5",
      borderColor: "#fdba74",
      color: "#9a3412"
    }
  };
  const getPillStyle = name => ({
    ...defaultPillStyle,
    ...pillStyles[name] || ({})
  });
  return <div className="not-prose my-4 rounded-lg border border-zinc-200 bg-zinc-50 px-4 py-3 text-sm dark:border-white/10 dark:bg-white/5">
      <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
        <span className="font-semibold text-zinc-700 dark:text-zinc-200">
          {label}:
        </span>
        {versions.map((v, i) => <span key={`${v.name}-${v.version}-${i}`} className="inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium" style={getPillStyle(v.name)}>
            <span>{v.name}</span>
            <span className="opacity-70">
              {v.version}
              {v.exact ? "" : "+"}
            </span>
          </span>)}
      </div>
    </div>;
};

To instrument Rack applications, AppSignal provides a Rack instrumentation middleware. If you use any of the supported Rack frameworks like [Rails], [Sinatra], [Hanami], [Grape], or [Padrino], we recommend using those instrumentations instead.

## Add the instrumentation middleware

<Compatibility versions={[{ name: "AppSignal for Ruby", version: "4.7.0" }]} />

<Tip>
  Using an older AppSignal Ruby gem? Follow [our legacy
  guide](#using-the-legacy-instrumentation-middleware).
</Tip>

To [integrate AppSignal][integrate] in a Rack application, we first need to load, [configure][configuration], and start AppSignal.

Then, instrument the Rack app by adding our Rack `EventMiddleware` and `InstrumentationMiddleware` to the middleware stack.

This documentation explains how to do this in your application's `config.ru` file.

<CodeGroup>
  ```ruby Ruby theme={null}
  # config.ru
  require "appsignal"                           # Load AppSignal

  Appsignal.start                               # Start the AppSignal integration

  # Add the Rack EventMiddleware first
  use Appsignal::Rack::EventMiddleware
  # Add the Rack InstrumentationMiddleware
  use Appsignal::Rack::InstrumentationMiddleware

  # Load your app with a require statement here, like
  require_relative "app"

  # Add other middleware here if needed

  # Finally, run the app
  use MyApp.run
  ```
</CodeGroup>

Ensure the `EventMiddleware` and `InstrumentationMiddleware` are registered in the application middleware stack as early as possible. The earlier these middleware are registered, the more request runtime the middleware will instrument. If other middleware are registered beforehand, our middleware will not instrument these other middleware.

After adding the `EventMiddleware` and `InstrumentationMiddleware` to your app's middleware stack, [the action](#setting-the-action-name) needs to be set for each route in your app in AppSignal. Without an action name to group requests, the event middleware will not report request information.

For more insights into the operation of your Rack application, we recommend [adding additional instrumentation][instrumentation] to the application's endpoints.

### The Rack event middleware

We recommend adding our Rack event middleware to all Rack applications. This middleware will ensure we track
The AppSignal Rack event middleware has the following features:

* Instrumentation of the request and recording a `process_request.rack` event.
* Reporting Exceptions that occur in the app and middleware.
* Tracking the response status code as the `response_status` tag on the sample.
* Tracking the response status code as the `response_status` metric, with the `namespace` and `status` tags.

### The Rack instrumentation middleware

We recommend that in addition to the `Appsignal::Rack::EventMiddleware`, the `AppSignal::Rack::InstrumentationMiddleware` is added to the app. This middleware supplements the event middleware's instrumentation by adding tags for the request path and request method, as well as tracking response body handling and response body closing operations.

The instrumentation middleware has the following features:

* Instrumentation of the request and recording a `process_request.rack` event.
* Reporting Exceptions that occur in the app.
* Tracking the request path and request method as tags on the sample.
* Instrumentation of the response body handling and recording a `process_response_body.rack` event for this operation.
* Instrumentation of the response body closing and recording a `close_response_body.rack` event for this operation.

## Using the legacy instrumentation middleware

<Compatibility versions={[{ name: "AppSignal for Ruby", version: "v1.1.6" }]} />

<Warning>
  The GenericInstrumentation middleware was deprecated in Ruby gem 3.10.0.
  Please use the [new guide](#add-the-instrumentation-middleware) instead.
</Warning>

To [integrate AppSignal][integrate] in a Rack application, we first need to load, [configure][configuration], and start AppSignal.

Then, instrument the Rack app by adding our Rack `GenericInstrumentation` middleware to the middleware stack.

This documentation explains how to do this in your application's `config.ru` file.

<CodeGroup>
  ```ruby Ruby theme={null}
  # config.ru
  # Load and configure AppSignal
  require "appsignal"                           # Load AppSignal

  Appsignal.config = Appsignal::Config.new(
    File.expand_path("../", __FILE__),          # Application root path
    ENV["RACK_ENV"],                            # Application environment
  )
  Appsignal.start                               # Start the AppSignal integration
  Appsignal.start_logger                        # Start logger

  # Load your app with a require statement here, like
  require_relative "app"

  # Add the GenericInstrumentation middleware
  use Appsignal::Rack::GenericInstrumentation

  # Add other middleware here if needed

  # Finally, run the app
  use MyApp.run
  ```
</CodeGroup>

Ensure the `EventMiddleware` and `InstrumentationMiddleware` are registered in the application middleware stack as early as possible. The earlier these middleware are registered, the more request runtime the middleware will instrument. If other middleware are registered beforehand, our middleware will not instrument these other middleware.

After adding the `EventMiddleware` and `InstrumentationMiddleware` to your app's middleware stack, [the action](#setting-the-action-name) needs to be set for each route in your app in AppSignal. Without an action name to group requests, the event middleware will not report request information.

For more insights into the operation of your Rack application, we recommend [adding additional instrumentation][instrumentation] to the application's endpoints.

## Setting the action name

Set an action name on the AppSignal transaction for a request so we can group endpoints in our issues and metrics. We recommend using a static action name per endpoint, like `GET /blog`, `POST /users`, `PUT /users/:id`, etc.

To set an action name for a request, call the `Appsignal.set_action` helper from the app.

<Warning>
  Do not use the request path of the route as the action name if the path has
  dynamic segments. Using real request paths for action names breaks our request
  grouping by creating unique issues for each possible request path.
</Warning>

<CodeGroup>
  ```ruby Ruby theme={null}
  # app.rb
  require "rack"

  # Example pure-Rack app
  class MyApp
    def call(env)
      case [env["REQUEST_METHOD"], env["PATH_INFO"]]
      when ["GET", "/"]
        Appsignal.set_action("GET /") # Action name set here
        body = <<~BODY
          <h1>Rack example app</h1>

          <ul>
            <li><a href="/slow">Slow request</a></li>
            <li><a href="/error">Error request</a></li>
          </ul>
        BODY
        [200, {"Content-Type" => "text/html"}, [body]]
      when ["GET", "/slow"]
        Appsignal.set_action("GET /slow") # Action name set here
        sleep 1
        [200, {"Content-Type" => "text/plain"}, ["Slow response"]]
      when ["GET", "/error"]
        Appsignal.set_action("GET /error") # Action name set here
        raise "uh oh"
      else
        Appsignal.set_action("NotFound") # Action name set here
        [404, {"Content-Type" => "text/plain"}, ["Page not found"]]
      end
    end
  end
  ```
</CodeGroup>

[configuration]: /ruby/configuration

[integrate]: /ruby/instrumentation/integrating-appsignal.html

[instrumentation]: /ruby/instrumentation/instrumentation.html

[Rails]: /ruby/integrations/rails.html

[Sinatra]: /ruby/integrations/sinatra.html

[Hanami]: /ruby/integrations/hanami.html

[Grape]: /ruby/integrations/grape.html

[Padrino]: /ruby/integrations/padrino.html
