CubeAPM
CubeAPM CubeAPM

How to Monitor ActiveMQ Queues and Consumers

How to Monitor ActiveMQ Queues and Consumers

Table of Contents

Apache ActiveMQ ships in two distinct products that share the name but have different monitoring architectures: ActiveMQ Classic (the original broker, currently on the 5.x and 6.x lines) and Apache Artemis (formerly ActiveMQ Artemis, now an independent Apache project since November 2025, which also powers Red Hat AMQ). Before setting up monitoring, confirm which broker you are running – the monitoring approach for ActiveMQ queues, metric names, and tooling are meaningfully different between the two.

ActiveMQ Classic (5.x / 6.x): Exposes metrics through JMX MBeans. Does not natively publish Prometheus-format metrics. The standard approach for Prometheus integration is the JMX Prometheus Exporter Java agent, which runs inside the broker JVM and converts JMX MBeans to Prometheus exposition format.

Apache Artemis: Ships with a native Micrometer-based metrics plugin that exports Prometheus-format metrics directly, with no external agent required. All Artemis-specific metrics use the artemis. prefix.

Key Takeaways

  • ActiveMQ Classic and Apache Artemis are different brokers with different metric names and monitoring architectures – confirm which one you are on before setting up monitoring. ActiveMQ Classic 6.x is a continuation of the Classic codebase, not Artemis
  • ActiveMQ Classic does not natively expose Prometheus metrics. Use the JMX Prometheus Exporter Java agent to bridge JMX MBeans to Prometheus
  • ActiveMQ Artemis has a native Prometheus plugin – one configuration line in broker.xml enables it with no external tooling needed
  • Queue depth (QueueSize in Classic, artemis.message.count in Artemis) is the primary consumer lag indicator for both brokers
  • ConsumerCount = 0 on any monitored queue is an immediate alert condition – messages accumulate with no one processing them
  • In ActiveMQ Classic, MemoryPercentUsage, StorePercentUsage, and TempStorePercentUsage are broker-wide resource metrics that cause message flow to stop when they hit 100%. Alert before they get there
  • Artemis surfaces artemis.unrouted.message.count – messages published to addresses with no queues. This metric has no Classic equivalent and catches a common misconfiguration

ActiveMQ Classic (5.x and 6.x) Monitoring

Primary Monitoring Interface: JMX

Apache ActiveMQ Classic has extensive JMX support. The broker exposes MBeans for the broker itself, each destination (queue and topic), each connection, and each consumer. JMX is enabled by default (useJmx=”true” in activemq.xml).

The MBean hierarchy for a queue is:

org.apache.activemq:type=Broker,brokerName=localhost,

  destinationType=Queue,destinationName=YourQueueName

Connect with JConsole for development:
# Local connection - no configuration needed

jconsole

# Select the ActiveMQ process from the list of local connections

Remote JMX connections are not enabled by default for security reasons. For production monitoring, the JMX Prometheus Exporter is the recommended path.

Exposing Classic Metrics to Prometheus: JMX Prometheus Exporter

The JMX Prometheus Exporter is a Java agent that attaches to the broker JVM, reads JMX MBeans, and serves them in Prometheus exposition format on a configurable HTTP port.

Install:

  1. Download jmx_prometheus_javaagent-<version>.jar from the Prometheus JMX Exporter GitHub releases
  2. Create a configuration YAML that maps the ActiveMQ MBean patterns to metric names

Minimal configuration for queue and broker metrics (activemq-jmx-config.yaml):

rules:

  # Queue depth - most important metric

  - pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>QueueSize'

    name: activemq_queue_size

    labels:

      brokerName: $1

      destinationName: $2

    help: "Number of messages in the queue (depth)"

    type: GAUGE
    

  # Consumer count per queue

  - pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>ConsumerCount'

    name: activemq_queue_consumer_count

    labels:

      brokerName: $1

      destinationName: $2

    help: "Number of active consumers on the queue"

    type: GAUGE
    

  # Enqueue rate (counter, use rate() in Prometheus)

  - pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>EnqueueCount'

    name: activemq_queue_enqueue_count_total

    labels:

      brokerName: $1

      destinationName: $2

    help: "Total messages enqueued since last restart"

    type: COUNTER


  # Dequeue rate (counter, use rate() in Prometheus)

  - pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>DequeueCount'

    name: activemq_queue_dequeue_count_total

    labels:

      brokerName: $1

      destinationName: $2

    help: "Total messages dequeued since last restart"

    type: COUNTER
    

  # Inflight messages (delivered to consumer, not yet acked)

  - pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>InFlightCount'

    name: activemq_queue_inflight_count

    labels:

      brokerName: $1

      destinationName: $2

    help: "Messages sent to consumers but not yet acknowledged"

    type: GAUGE
    

  # Expired messages

  - pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>ExpiredCount'

    name: activemq_queue_expired_count_total

    labels:

      brokerName: $1

      destinationName: $2

    help: "Total messages expired since last restart"

    type: COUNTER
    

  # Broker memory usage percentage (0-100)

  - pattern: 'org.apache.activemq<type=Broker, brokerName=(.+)><>MemoryPercentUsage'

    name: activemq_broker_memory_percent_usage

    labels:

      brokerName: $1

    help: "Percentage of broker memory limit in use"

    type: GAUGE
    

  # Broker store usage percentage (0-100)

  - pattern: 'org.apache.activemq<type=Broker, brokerName=(.+)><>StorePercentUsage'

    name: activemq_broker_store_percent_usage

    labels:

      brokerName: $1

    help: "Percentage of persistent store space in use"

    type: GAUGE
    

  # Temp store usage percentage (0-100)

  - pattern: 'org.apache.activemq<type=Broker, brokerName=(.+)><>TempPercentUsage'

    name: activemq_broker_temp_percent_usage

    labels:

      brokerName: $1

    help: "Percentage of temp store space in use"

    type: GAUGE
    

  # Average enqueue time in milliseconds

  - pattern: 'org.apache.activemq<type=Broker, brokerName=(.+), destinationType=Queue, destinationName=(.+)><>AverageEnqueueTime'

    name: activemq_queue_average_enqueue_time_ms

    labels:

      brokerName: $1

      destinationName: $2

    help: "Average time messages spend waiting in the queue (ms)"

    type: GAUGE

Enable the agent in bin/env:

ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS -javaagent:/path/to/jmx_prometheus_javaagent.jar=9404:/path/to/activemq-jmx-config.yaml"

Metrics are served at http://broker-host:9404/metrics.

Key JMX MBean Attributes for Classic Queues

These attributes are available on the queue destination MBean:

JMX AttributeWhat it measuresNotes
QueueSizeCurrent number of messages in the queue (depth)Primary lag indicator
ConsumerCountMessages delivered to consumers, not yet acknowledged0 = no one processing
EnqueueCountTotal messages enqueued since last restartCounter – use rate()
DequeueCountTotal messages dequeued and acknowledgedCounter – use rate()
InFlightCountMessages delivered to consumers, not yet ackedHigh value = slow consumers
DispatchCountTotal messages dispatched (dequeued + inflight)Counter
ExpiredCountMessages that expired before deliveryNon-zero = messages being lost
AverageEnqueueTimeAverage time a message spends waiting (ms)Rising = consumer slowdown
MemoryPercentUsage% of queue memory limit used100% = flow control active

Broker-level MBean attributes (critical for avoiding full stops):

JMX AttributeAlert thresholdWhat happens at 100%
MemoryPercentUsage> 70% warning, > 85% criticalBroker blocks all producers
StorePercentUsage> 70% warning, > 85% criticalBroker blocks all producers
TempPercentUsage> 75% warningBroker blocks non-persistent sends

Important: When MemoryPercentUsage or StorePercentUsage reaches 100%, the broker triggers flow control and blocks all producer connections across the entire broker – not just the queue that caused the pressure. This is a broker-wide outage for producers.

PromQL Alerts for ActiveMQ Classic

# Alert: No consumers on a monitored queue for 2 minutes

activemq_queue_consumer_count == 0


# Alert: Queue depth growing continuously

activemq_queue_size > 0

  and (activemq_queue_size - activemq_queue_size offset 10m) > 0
  

# Alert: Broker memory critical

activemq_broker_memory_percent_usage > 85


# Alert: Persistent store critical  

activemq_broker_store_percent_usage > 85


# Alert: Messages expiring (data loss)

rate(activemq_queue_expired_count_total[5m]) > 0


# Alert: Enqueue rate exceeds dequeue rate (backlog growing)

rate(activemq_queue_enqueue_count_total[5m]) 

  - rate(activemq_queue_dequeue_count_total[5m]) > 0

Note on EnqueueCount and DequeueCount: These counters reset to zero when the broker restarts. In Prometheus, use rate() or increase() functions for rate-based alerting. For QueueSize, use the value directly as it is a gauge.

JMX MBean Suppression at Scale

At high queue counts (tens of thousands of queues), JMX MBean registration for every consumer and producer becomes expensive. Starting with ActiveMQ Classic 5.12, you can selectively suppress MBean registration:

<managementContext>

  <managementContext 

    suppressMBean="endpoint=dynamicProducer,endpoint=Consumer,

    connectionName=*,destinationName=ActiveMQ.Advisory.*"/>

</managementContext>

This reduces monitoring overhead while keeping broker and destination-level MBeans visible.

Apache Artemis Monitoring (Formerly ActiveMQ Artemis)

Enabling the Native Prometheus Plugin

Artemis exports metrics via Micrometer. To enable Prometheus-format output, configure a metrics plugin in broker.xml:

<configuration>

  <core>

    <!-- ... other config ... -->

    <metrics>

      <jvm-memory>true</jvm-memory>

      <jvm-gc>true</jvm-gc>

      <jvm-threads>true</jvm-threads>

      <file-descriptors>true</file-descriptors>

      <plugin class-name="org.apache.activemq.artemis.core.server.metrics.plugins.ArtemisPrometheusMetricsPlugin"/>

    </metrics>

  </core>

</configuration>

After restarting, metrics are served at the broker’s management web server, typically:

http://broker-host:8161/metrics

All Artemis-specific broker metrics use the artemis. prefix. JVM metrics provided by Micrometer do not use the artemis. prefix.

Key Artemis Metrics

Queue-level metrics (tagged with address and queue labels):

MetricWhat it measures
artemis.message.countCurrent messages in the queue (depth)
artemis.messages.addedTotal messages added since startup (counter)
artemis.messages.acknowledgedTotal messages acknowledged (counter)
artemis.consumer.countActive consumers currently attached
artemis.delivering.countMessages currently being delivered to consumers
artemis.messages.expiredTotal expired messages (counter)
artemis.scheduled.message.countMessages scheduled for future delivery
artemis.durable.message.countDurable messages currently in queue

Address-level metrics (tagged with address label):

MetricWhat it measures
artemis.unrouted.message.countMessages published to addresses with no queues

Broker-level metrics (tagged with broker label):

MetricWhat it measures
artemis.connection.countTotal active connections to the broker
artemis.total.message.countTotal messages across all queues
artemis.disk.store.usageDisk store space used as a fraction (0.0 to 1.0)

Important note on total message count: Artemis does not expose a single broker-wide total message count metric directly. The documentation explicitly states: “It may appear that some higher-level broker metrics are missing (e.g., total message count). However, these metrics can be deduced by aggregating the lower-level metrics.” Aggregate artemis.message.count across all queues to get the cluster total.

PromQL Alerts for ActiveMQ Artemis

# Alert: No consumers on a queue

artemis_consumer_count{queue="your-queue-name"} == 0


# Alert: Queue depth growing

artemis_message_count > 0

  and (artemis_message_count - artemis_message_count offset 10m) > 0
  

# Alert: Unrouted messages (misconfigured address/queue binding)

artemis_unrouted_message_count > 0


# Alert: Messages expiring (data loss)

rate(artemis_messages_expired[5m]) > 0


# Alert: High disk store usage

artemis_disk_store_usage > 0.85


# Alert: Enqueue rate exceeds ack rate (backlog growing)

rate(artemis_messages_added[5m]) 

  - rate(artemis_messages_acknowledged[5m]) > 0

Note on Prometheus metric name format: Micrometer converts . in metric names to _ when exporting to Prometheus. So artemis.message.count becomes artemis_message_count in Prometheus queries.

Metrics Comparison: Classic vs Artemis

What you need to monitorActiveMQ ClassicActiveMQ Artemis
Queue depthQueueSize (JMX) / activemq_queue_size (Prometheus)artemis_message_count
Consumer countConsumerCount (JMX) / activemq_queue_consumer_countartemis_consumer_count
In-flight messagesInFlightCount (JMX)artemis_delivering_count
Messages added rateEnqueueCount (JMX counter)artemis_messages_added (counter)
Messages processed rateDequeueCount (JMX counter)artemis_messages_acknowledged (counter)
Expired messagesExpiredCount (JMX)artemis_messages_expired
Broker memory pressureMemoryPercentUsage (0-100%)JVM memory metrics via Micrometer
Persistent store pressureStorePercentUsage (0-100%)artemis_disk_store_usage (0.0 to 1.0)
Unrouted messagesNot availableartemis_unrouted_message_count
Prometheus supportVia JMX Prometheus Exporter agentNative Micrometer plugin

The Web Console

Both brokers ship with a web console for interactive monitoring:

  • ActiveMQ Classic: Management console at http://broker-host:8161/admin (default credentials: admin/admin – change before production use). Shows queue depth, consumer count, and message rates per destination.
  • ActiveMQ Artemis: Hawtio-based console at http://broker-host:8161/console (default credentials: admin/admin – change before production use). Shows per-queue and per-address metrics, active consumers, and message browsing.

The web console is useful for development and ad-hoc investigation. For production alerting and trend analysis, use JMX with Prometheus (Classic) or the native Prometheus plugin (Artemis) combined with Grafana.

How Do I Find Which Application Is Causing an ActiveMQ Queue Backlog?

The queue depth rising on a monitored queue tells you messages are accumulating. It does not tell you which producer is sending faster than consumers can process, whether the consumer is blocked on a downstream call, or which message type is dominating the backlog.

When activemq_queue_size or artemis_message_count climbs on a monitored queue, the debugging path through JMX or Prometheus alone requires correlating producer send rates, consumer ack rates, and broker-side metrics manually – none of which connect to the application request that generated or consumed each message.

CubeAPM instruments your producer and consumer application services via OpenTelemetry and captures each message publish and consume operation as a span in the full distributed trace.  When a queue depth alarm fires, the trace in CubeAPM shows which API endpoint is generating the publish load, which consumer service is processing messages, how long each message takes to process end-to-end, and whether the bottleneck is within the consumer’s own logic or in a downstream service it calls. The metric identifies the symptom. The trace identifies where in your application the imbalance originated. Self-hosted inside your own infrastructure, no data leaves your environment.

Summary

MetricClassic equivalentArtemis equivalentAlert when
Queue depthactivemq_queue_sizeartemis_message_countContinuously growing
Consumer countactivemq_queue_consumer_countartemis_consumer_count= 0 for > 2 minutes
In-flight / deliveringactivemq_queue_inflight_countartemis_delivering_countGrowing without dequeue growth
Expired messagesactivemq_queue_expired_count_totalartemis_messages_expiredAny non-zero rate
Broker memoryactivemq_broker_memory_percent_usageJVM heap metrics> 85%
Persistent storeactivemq_broker_store_percent_usageartemis_disk_store_usage> 85% (Classic) / > 0.85 (Artemis)
Unrouted messagesNot availableartemis_unrouted_message_count> 0

Start with queue depth and consumer count alerts for every monitored queue. Add broker memory and store usage alarms to prevent broker-wide flow control events. Enable expired message alerting for any queue with a message TTL configured. Use the web console for ad-hoc investigation and Prometheus plus Grafana for continuous alerting and trend analysis.

Disclaimer: JMX attribute names, Prometheus metric names, configuration examples, and alert thresholds are for guidance only – verify against current ActiveMQ Classic documentation and ActiveMQ Artemis documentation before applying to production. Metric names and behaviors may vary between minor versions. Default web console credentials must be changed before any production deployment. CubeAPM references reflect genuine use cases; evaluate all tools against your own requirements.

Also read:

What Are the Most Important RabbitMQ Metrics to Track?

How to Monitor AWS Fargate Containers with OpenTelemetry

How to Monitor AWS DynamoDB Read/Write Capacity and Throttles

×
×