> ## 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.

# AppSignal Ruby Collector Configuration

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>;
};

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

Use collector mode to send data to AppSignal through the [AppSignal Collector](/collector). [Distributed tracing](/distributed-tracing) is only supported when sending data through an AppSignal hosted collector. By the end of this page, your app will report to the collector you choose, and each service will identify itself with its own service name.

This page assumes that you have already followed [the installation instructions](/ruby/installation).

<h2 id="requirements">
  Requirements
</h2>

Collector mode requires **Ruby 3.1 or newer**. On older Ruby versions the `collector_endpoint` option is ignored.

Collector mode does not support **JRuby**. It depends on how Ruby handles forking, which JRuby does something different with.

<h2 id="installing-the-opentelemetry-gems">
  Installing the OpenTelemetry gems
</h2>

Collector mode sends data using OpenTelemetry. The `appsignal` gem does not install the OpenTelemetry gems, so add `appsignal-opentelemetry` next to the `gem "appsignal"` line already in your `Gemfile`:

<CodeGroup>
  ```ruby title="Gemfile" theme={null}
  gem "appsignal"
  gem "appsignal-opentelemetry"
  ```
</CodeGroup>

Then run `bundle install`.

The `appsignal-opentelemetry` gem does nothing on its own. It only installs the OpenTelemetry gem versions that collector mode supports, so you do not have to track them yourself. Its version matches the `appsignal` gem, so `appsignal-opentelemetry` 5.0.0 pairs with `appsignal` 5.0.0.

If those gems are missing or their versions are unsupported, AppSignal logs a warning at startup and does not enter collector mode.

<h2 id="deploying-a-collector">
  Deploying a collector
</h2>

You can have AppSignal host a collector for you using the ["Hosted Collector"](https://appsignal.com/redirect-to/organization?to=admin/hosted_collectors) page in your organization's settings.

<h2 id="configuring-the-collector">
  Configuring the collector
</h2>

Set [the `collector_endpoint` configuration option](/ruby/configuration/options#option-collector_endpoint) to your collector's base URL. When using a hosted collector, copy the "Collector URL" from the "Hosted Collector" settings page.

Set [the `service_name` option](/ruby/configuration/options#option-service_name) to identify this application in traces. Use a different value for each service, such as `web-server` or `background-worker`.

<CodeGroup>
  ```ruby title="config/appsignal.rb" theme={null}
  Appsignal.configure do |config|
    # ... other settings ...
    config.collector_endpoint = "https://collector.example"
    config.service_name = "web-server"
  end
  ```

  ```sh title="Environment variables" theme={null}
  APPSIGNAL_COLLECTOR_ENDPOINT="https://collector.example"
  APPSIGNAL_SERVICE_NAME="web-server"
  ```
</CodeGroup>

AppSignal for Ruby now sends its traces, metrics, and logs to the configured collector.

To check that AppSignal loaded these settings, run `bundle exec appsignal diagnose --no-send-report` and confirm that the `Configuration` section lists the expected `collector_endpoint` and `service_name`. Then send a request or run a job and confirm its trace appears in AppSignal.

AppSignal builds its traces out of OpenTelemetry spans when it reports to a collector. Read [AppSignal for Ruby and OpenTelemetry](/ruby/instrumentation/opentelemetry) for how to describe those spans yourself, and how AppSignal works together with instrumentation you write with the OpenTelemetry SDK.

<h2 id="migrating">
  Migrating to collector mode
</h2>

Most configuration options have the same behavior in agent mode and collector mode.

In collector mode, some data that was sent in agent mode as a single kind of data is split between multiple data types. Some configuration options that controlled whether that data was sent and how it was filtered have changed:

| Agent mode | Collector mode |
| - | - |
| [`request_headers`](/ruby/configuration/options#option-request_headers) | [`keep_request_headers`](/ruby/configuration/options#option-keep_request_headers), [`keep_request_environment`](/ruby/configuration/options#option-keep_request_environment) |
| [`filter_parameters`](/ruby/configuration/options#option-filter_parameters) | [`filter_request_payload`](/ruby/configuration/options#option-filter_request_payload), [`filter_function_parameters`](/ruby/configuration/options#option-filter_function_parameters), [`filter_request_query_parameters`](/ruby/configuration/options#option-filter_request_query_parameters) |
| [`send_params`](/ruby/configuration/options#option-send_params) | [`send_request_payload`](/ruby/configuration/options#option-send_request_payload), [`send_function_parameters`](/ruby/configuration/options#option-send_function_parameters), [`send_request_query_parameters`](/ruby/configuration/options#option-send_request_query_parameters) |

When the collector mode options are not set, the agent mode option is used to derive a value for it, so an application that configured these config options for agent mode will still report the same data in collector mode.

You can set the collector mode options to report each kind of data differently, such as filtering a background job's arguments but not a request's payload. AppSignal logs which values to set to keep reporting the same data, and [`appsignal diagnose`](/ruby/command-line/diagnose) shows them as loaded from `derived`:

```yaml Diagnose output theme={null}
keep_request_headers: ["accept"]
  Sources:
    default: ["accept", "accept-charset", "accept-encoding", "accept-language", "cache-control", "connection", "content-length", "range"]
    derived: ["accept"]
```

<h3 id="request-headers">
  Request headers
</h3>

`request_headers` lists [Rack environment](https://rack.github.io/) keys, and only some of those keys hold a request header. Collector mode reports the two separately, each under the names its own kind of value goes by:

* `keep_request_headers` lists request headers, lowercase and dash-separated, as OpenTelemetry names them. `HTTP_ACCEPT` becomes `accept`.
* `keep_request_environment` lists the rest, as Rack names them. `QUERY_STRING` stays `QUERY_STRING`.

The trace view shows the first in its **Request headers** panel and the second in its **Environment** panel.

<h3 id="parameters">
  Parameters
</h3>

Collector mode reports three kinds of parameters, each with its own filter and send option:

* The **request payload**: an incoming HTTP request's parameters, such as a form body.
* The **function parameters**: the arguments a background job was given.
* The **request query parameters**: an incoming HTTP request's parsed query string.

Read [request parameters](/guides/custom-data/request-parameters) for more information on how to report parameters.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.