# Instrument Queues | Sentry for Laravel

Sentry comes with a [queue-monitoring dashboard](https://sentry.io/orgredirect/organizations/:orgslug/insights/backend/queues.md) that can be auto-instrumented by our [Laravel SDK](https://docs.sentry.io/platforms/php/guides/laravel.md).

If you're using something else, you can manually instrument your queue producers and consumers to ensure that you have performance data about your messaging queues.

## [Producer Instrumentation](https://docs.sentry.io/.md#producer-instrumentation)

Wrap your queue producer code into a span. Your span `op` must be set to `queue.publish`. Include the following span data to enrich your producer spans with additional metrics:

| Data Attribute                | Type   | Description                       |
| ----------------------------- | ------ | --------------------------------- |
| `messaging.message.id`        | string | The message identifier            |
| `messaging.destination.name`  | string | The queue or topic name           |
| `messaging.message.body.size` | int    | Size of the message body in bytes |

Make sure that there's a transaction running when you create the spans. See [Tracing](https://docs.sentry.io/platforms/php/guides/laravel/tracing.md) for more information.

You must also include Sentry's trace headers (`sentry-trace` and `baggage`) in your queue job's payload so that your consumers can continue your trace once your job is picked up.

```php
$parentSpan = \Sentry\SentrySdk::getCurrentHub()->getSpan();

if ($parentSpan !== null) {
    $context = \Sentry\Tracing\SpanContext::make()
        ->setOp('queue.publish')
        ->setDescription('App\Jobs\MyJob');

    $span = $parentSpan->startChild($context);

    \Sentry\SentrySdk::getCurrentHub()->setSpan($span);

    // Publish your job to the queue
    Queue::push($job, [
        'publish_time' => microtime(true),
        'sentry_trace' => \Sentry\getTraceparent(),
        'baggage' => \Sentry\getBaggage(),
    ]);
    
    $span
        ->setData([
            'messaging.message.id' => $job->getId(),
            'messaging.destination.name' => $job->getQueue(),
            'messaging.message.body.size' => $job->getSize(),
        ])
        ->finish();

    \Sentry\SentrySdk::getCurrentHub()->setSpan($parentSpan);
}
```

## [Consumer Instrumentation](https://docs.sentry.io/.md#consumer-instrumentation)

Wrap your queue consumer code into a span. Your span `op` must be set to `queue.process`. Include the following span data to enrich your consumer spans with additional metrics:

| Data Attribute                      | Type   | Description                                                         |
| ----------------------------------- | ------ | ------------------------------------------------------------------- |
| `messaging.message.id`              | string | The message identifier                                              |
| `messaging.destination.name`        | string | The queue or topic name                                             |
| `messaging.message.body.size`       | number | Size of the message body in bytes                                   |
| `messaging.message.retry.count`     | number | The number of times a message was attempted to be processed         |
| `messaging.message.receive.latency` | number | The time in milliseconds that a message awaited processing in queue |

Make sure that there's a transaction running when you create the spans. See [Tracing](https://docs.sentry.io/platforms/php/guides/laravel/tracing.md) for more information.

Use `\Sentry\continueTrace()` to connect your consumer transaction to their associated producer spans, and `$transaction->setStatus()` to mark the trace of your message as success or failed.

```php
$context = \Sentry\continueTrace(
    $job->getMetadata('sentry_trace'),
    $job->getMetadata('baggage')
)
    ->setOp('queue.process')
    ->setName('App\Jobs\MyJob');

$transaction = \Sentry\startTransaction($context);

\Sentry\SentrySdk::getCurrentHub()->setSpan($transaction);

$job = Queue::pop();

try {
    // Continue job processing...
} catch (\Throwable $e) {
    $transaction->setStatus(\Sentry\Tracing\SpanStatus::internalError());
}

$transaction
    ->setData([
        'messaging.message.id' => $job->getId(),
        'messaging.destination.name' => $job->getQueue(),
        'messaging.message.body.size' => $job->getSize(),
        'messaging.message.receive.latency' =>  microtime(true) - $job->getMetadata('publish_time'),
        'messaging.message.retry.count' => $job->getRetryCount(),
    ])
    ->finish();
```
