Skip to content
RabbitMQ · How-to Intermediate

Track RabbitMQ queue depth and consumer lag with OpenTelemetry

Stream RabbitMQ queue metrics into Sluicio with the OpenTelemetry Collector — so you can see a backlog forming and get paged before messages pile up.

SLSluicio team 9 min read Updated Sep 2026

Queue depth is the earliest signal that an integration is falling behind. When the number of ready messages on a RabbitMQ queue starts climbing, your consumers can’t keep up — and every message that lands after that waits a little longer. This guide points the OpenTelemetry Collector at RabbitMQ’s management API, streams per-queue metrics into Sluicio, and turns a growing backlog into an alert.

No application code changes are needed: the Collector polls RabbitMQ over HTTP and exports standard OTLP metrics.

The receiver reads from RabbitMQ’s management HTTP API (port 15672). Enable the plugin and create a read-only user scoped to monitoring only:

Terminal window
# Expose the management HTTP API on :15672
rabbitmq-plugins enable rabbitmq_management
# A read-only user tagged 'monitoring' — no queue read/write/configure rights
rabbitmqctl add_user monitoring "$RABBITMQ_MONITOR_PASSWORD"
rabbitmqctl set_user_tags monitoring monitoring
rabbitmqctl set_permissions -p / monitoring "^$" "^$" ".*"

Add the rabbitmq receiver, a resource processor that names the broker’s service, and an OTLP exporter that points at Sluicio. Secrets come from the environment, so nothing sensitive lives in the file.

otel-collector-config.yaml
receivers:
rabbitmq:
endpoint: http://localhost:15672
username: monitoring
password: ${env:RABBITMQ_MONITOR_PASSWORD}
collection_interval: 30s
processors:
# The rabbitmq receiver sets no service.name. Name the broker here,
# or every queue's metrics arrive under unknown_service.
resource/broker:
attributes:
- key: service.name
value: rabbitmq
action: upsert
exporters:
otlp_http/sluicio:
endpoint: https://your-instance-name.sluicio.com
headers:
authorization: Bearer ${env:SLUICIO_INGEST_KEY}
service:
pipelines:
metrics:
receivers: [rabbitmq]
processors: [resource/broker]
exporters: [otlp_http/sluicio]

The resource processor is what makes the metrics usable per queue. Every queue arrives under one service, rabbitmq, with its name in rabbitmq.queue.name, so each queue can become an integration of its own. Without it the service name is missing and Sluicio files everything under unknown_service.

Terminal window
docker run --rm \
-v "$(pwd)/otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml" \
-e RABBITMQ_MONITOR_PASSWORD \
-e SLUICIO_INGEST_KEY \
otel/opentelemetry-collector-contrib:0.157.0

Within a collection interval or two, the rabbitmq service shows up in Sluicio with live metrics for every queue.

The receiver emits one set of metrics per queue, tagged with the queue, vhost, and node as resource attributes (rabbitmq.queue.name, rabbitmq.vhost.name, rabbitmq.node.name).

MetricWhat it tells you
rabbitmq.message.current {state=ready}Queue depth — messages waiting for a consumer. This is your backlog.
rabbitmq.message.current {state=unacknowledged}Delivered but not yet acked — work currently in flight.
rabbitmq.consumer.countHow many consumers are attached to the queue.
rabbitmq.message.publishedSource for the publish rate (messages in).
rabbitmq.message.deliveredSource for the delivery rate (messages out to consumers).
rabbitmq.message.acknowledgedSource for the throughput rate (work completed).
rabbitmq.message.droppedMessages dropped — e.g. unroutable or no matching queue.

There’s no single “lag” number — you read it from how the rates move together:

  • Backlog growing: ready is trending up. Publishers are outrunning consumers.
  • Falling behind: publish rate is consistently higher than the acknowledged rate.
  • Stuck consumers: rabbitmq.consumer.count is 0 while ready > 0 — nothing is draining the queue at all.

In Sluicio, add a queue-depth panel grouped by rabbitmq.queue.name, and overlay publish vs. acknowledged rate to see the gap open up.

Two alerts cover most cases:

  • Sustained backlog — rabbitmq.message.current{state=ready} for a queue stays above your threshold for N minutes (e.g. > 1000 for 5 min). The duration matters: a brief spike during a burst is normal; a sustained climb is not.
  • Stalled queue — rabbitmq.consumer.count == 0 while ready > 0. This catches a crashed or disconnected consumer immediately, before depth even has time to grow.

Often a queue is the integration: invoices go out to the finance partner through invoices.outbound, and the team that owns that flow cares about that queue and no other. Make it an integration of its own:

  1. New integration, and add the service rabbitmq.
  2. Edit its row and add a condition: rabbitmq.queue.name is invoices.outbound.

The row shows how many metric series the condition matches, so a misspelled queue name shows up as zero before you save. The integration’s Metrics tab then shows that one queue, and it reads ok while the queue reports.

To make its health follow the queue, bind a check to the integration on its Alerting tab: rabbitmq.message.current, state is ready, above your threshold. There’s no need to name the queue in the check: bound to the integration, it reads that queue alone. The integration turns unhealthy when its queue backs up, and ok again when it drains.

Metric-only integrations like this need Sluicio v0.11.169 or later; before it they read “Quiet” and the services editor could not see the queue. A check bound to one reads its queue alone from v0.11.170; on v0.11.169, name the queue in the check as well (rabbitmq.queue.name is invoices.outbound), or it reads every queue on the broker.