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

# Delayed::Job

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

[Delayed::Job](https://github.com/collectiveidea/delayed_job) is one of the most popular background processors for Ruby and Rails, originally created at [Shopify](https://shopifyengineering.myshopify.com/).

The AppSignal gem detects Delayed Job when it's present and hooks into the standard Delayed Job callbacks. No further action is required to enable integration.

This integration aims to support all the different Delayed::Job enqueuing methods. Some methods may have limitations or customization options.

## Classes with `#perform` methods

<Tip>
  **Note**: Reporting of jobs using this method is supported since AppSignal
  Ruby gem version 2.11.0.
</Tip>

Delayed Job supports enqueuing jobs based on instances of classes or structs that listen to a `perform` instance method, when enqueued with `Delayed::Job.enqueue`. AppSignal will use the object's class name as the action naming, appending `#perform` to the action name. A job for `StructJob` is reported as `StructJob#perform`.

<CodeGroup>
  ```ruby Ruby theme={null}
  class StructJob < Struct.new(:id)
    def perform
      # Do stuff
    end
  end

  Delayed::Job.enqueue(StructJob.new("id"))
  # Reported as "StructJob#perform"
  ```
</CodeGroup>

Note that this method of enqueuing does not support arguments as a whole object is enqueued. Job objects are serialized when enqueued and deserialized when processed. AppSignal does not read the state of the deserialized object. The argument `id` for the `StructJob` in the example above is not reported.

## Jobs using `display_name`

Delayed Job allows any class to define its own `display_name`. This `display_name` value can interfere with AppSignal's reporting if it is built using dynamic values, such as the arguments given to the job.

If the `display_name` method return value does not return a String with the `ClassName#method_name` format, AppSignal treats each job as a separate entity, creating many Incidents and notifications. This breaks the grouping AppSignal does for these jobs, resulting in AppSignal reporting many unique variations of incidents for the job, and unusable metrics in graphs.

To prevent this from happening, define an `appsignal_name` method that returns a job name using the `ClassName#method_name` format. This way the jobs will be grouped correctly again.

<CodeGroup>
  ```ruby Ruby theme={null}
  class StructJobWithName < Struct.new(:id)
    def perform
      # Do stuff
    end

    # This returns an unique job name, creating new incidents and graphs for each
    # unique job name.
    def display_name
      "StructJobWithName-#{id}"
    end

    # This will group the jobs back to a single entity, allowing incidents
    # and graphs to work properly.
    def appsignal_name
      "StructJobWithName#perform"
    end
  end

  Delayed::Job.enqueue(StructJobWithName.new("id"))
  # Reported as "StructJobWithName#perform"
  ```
</CodeGroup>

## Delay method call support

Method calls queued with the delay extension will be reported with an action name similar to how they are called.

The arguments given to the delayed method will be reported as the arguments for the job.

<CodeGroup>
  ```ruby Ruby theme={null}
  Post.delay.archive_all("some selector")
  # Reported as "Post.archive_all"

  Post.create(:title => "Post title").delay.send_mail("mail subject")
  # Reported as "Post#send_mail"
  ```
</CodeGroup>

## Delayed::Job.enqueue support

<Tip>
  **Note**: Job name detection was added in Ruby gem version 2.11.0.
</Tip>

Custom jobs objects enqueued with `Delayed::Job.enqueue` will be reported as normal, but will not report arguments. A whole object is given to Delayed::Job, and serialized into YAML and back. We can't detect arguments in this scenario.

<CodeGroup>
  ```ruby Ruby theme={null}
  Delayed::Job.enqueue job_object
  ```
</CodeGroup>

## Enqueue instrumentation

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

Enqueuing a job with Delayed::Job records an `enqueue.delayed_job` event, titled after the job being enqueued. If a job defines an `appsignal_name`, the enqueue event uses it, the same way the performed job's action name does.

AppSignal records enqueue events on the active transaction's event timeline, for example when you enqueue a job from within a web request or from within another job. It only records them when a transaction is active, so enqueuing a job outside of a transaction records nothing.

To stop recording enqueue events across all background job integrations, set the [`enable_job_enqueue_instrumentation` config option](/ruby/configuration/options#option-enable_job_enqueue_instrumentation) to `false`. This does not affect the instrumentation of the jobs themselves.

## Active Job support

The Delayed Job integration is compatible with [Active Job](/ruby/integrations/active-job). It will report [queue times in graphs](https://appsignal.com/redirect-to/app?to=performance/graphs), queues and priorities if set on the job.

Upgrade to version 2.11.0 of the Ruby gem or newer for improved support.

## Changes to the integration

### Queue time

In AppSignal for Ruby gem 2.3.0 a change was made to the queue time registration. In [PR #297](https://github.com/appsignal/appsignal-ruby/pull/297) the start time of the job was used rather than the creation time of the job.

This means that the time from when a job was created until the time it should start is no longer registered as queue time. This will prevent very long queue times from skewing the queue time graphs on AppSignal.com.

## Example applications

Below is a list of example apps available to test the Delayed::Job integration with:

* [AppSignal + Rails 5 + Delayed::Job](https://github.com/appsignal/appsignal-examples/tree/rails-5+delayed_job)
  * The example shows how to set up AppSignal with Delayed::Job and Rails. In the `README` file it lists all known and tested methods of enqueuing jobs that AppSignal supports.
