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

# @boringnode/queue

> Instrument @boringnode/queue job queues for observability

This guide covers how to instrument `@boringnode/queue` for monitoring background jobs. You will learn how to:

* Install and configure the instrumentation
* Track job dispatch and processing
* Understand producer and consumer spans

For the full list of required span attributes and what powers the Jobs dashboard, see the [Jobs feature page](/features/jobs).

## Installation

```bash theme={"theme":"vesper"}
npm install @boringnode/queue
```

The OTel instrumentation is built into `@boringnode/queue` itself. No additional package is needed.

## Usage

Create an instance of `QueueInstrumentation` and call `enable()`. This must happen before you call `QueueManager.init()`.

```typescript title="instrumentation.ts" theme={"theme":"vesper"}
import { QueueInstrumentation } from "@boringnode/queue/otel";

const instrumentation = new QueueInstrumentation();
instrumentation.enable();
```

Once enabled, the instrumentation automatically patches `QueueManager.init()` to inject tracing wrappers. All job dispatches and worker executions will create spans.

If the automatic patching does not work (e.g., ESM hook timing issues), you can register manually:

```typescript title="instrumentation.ts" theme={"theme":"vesper"}
import * as queue from "@boringnode/queue";

instrumentation.manuallyRegister(queue);
```

<Tip>
  If you are using AdonisJS with the Monocle agent, this instrumentation is configured automatically when `@boringnode/queue` is installed. No manual setup is needed.
</Tip>

## Configuration

```typescript theme={"theme":"vesper"}
const instrumentation = new QueueInstrumentation({
  // Messaging system name used in span attributes (default: "boringqueue")
  messagingSystem: "boringqueue",

  // How consumer spans relate to producer spans (default: "link")
  executionSpanLinkMode: "link",
});
```

### Span linking vs parenting

By default, consumer spans are **linked** to the producer span. This means they appear as separate traces connected by a link. Set `executionSpanLinkMode: "parent"` to make the consumer span a **child** of the producer, keeping them in the same trace.

## Spans

### Producer spans

When you dispatch a job, the instrumentation creates a **PRODUCER** span named `publish {queueName}`. Trace context is injected into the job payload so the consumer can link back to the producer.

For batch dispatches, a single PRODUCER span is created with a `messaging.batch.message_count` attribute.

### Consumer spans

When a worker processes a job, the instrumentation creates a **CONSUMER** span named `process {queueName}`. The span captures job metadata, queue wait time, and any errors thrown during processing.

If the job is retried, a `messaging.retry` event is recorded on the span with the next retry timestamp.

### Internal operation suppression

Internal queue operations (Redis calls, etc.) are automatically suppressed to keep traces clean. Only the high-level dispatch and execution spans are visible.

## Span attributes

In addition to the [standard job attributes](/features/jobs#span-attributes), the `@boringnode/queue` instrumentation emits these attributes:

| Attribute                       | Description                                    |
| ------------------------------- | ---------------------------------------------- |
| `messaging.job.name`            | Job class name                                 |
| `messaging.job.queue_time_ms`   | Time between dispatch and execution start (ms) |
| `messaging.job.group_id`        | Job group ID (if set)                          |
| `messaging.job.priority`        | Job priority (if set)                          |
| `messaging.job.delay_ms`        | Job delay in ms (if set)                       |
| `messaging.message.retry.count` | Number of retry attempts                       |
