Prometheus Metrics
Scrape KubeMQ's always-on Prometheus endpoint — every metric series for messaging, queues, RPC latency, cluster health, and the agent platform.
KubeMQ exposes an always-on Prometheus exporter that reports message counts, byte volumes, client counts, queue health, RPC latency, cluster state, and agent-platform activity. It needs no configuration — it is running the moment KubeMQ starts.
Overview
The Prometheus exporter is always on. The same in-process metrics also power the built-in dashboard and its snapshot system, so the numbers you scrape with Prometheus and the numbers you see in the dashboard come from one source.
Metrics are served in-process by the management API at
GET /metrics on the management API port (:8080) — the same port that serves health
probes, stats, and the dashboard. There is no separate listener and no extra setup; the
endpoint returns standard Prometheus text format.
Prometheus is the pull path and is always on. KubeMQ also supports an opt-in
push path — OpenTelemetry metrics over OTLP — covered on the
Distributed Tracing page. The OTel pending instrument
(active in-flight messages) is exported only over OTLP; there is no equivalent Prometheus
series.
Scraping KubeMQ
Read the endpoint directly with curl:
curl http://localhost:8080/metricsPoint Prometheus at the same endpoint with a scrape_config:
scrape_configs:
- job_name: kubemq
metrics_path: /metrics
static_configs:
- targets: ["kubemq:8080"]Labels
Core messaging metrics carry a shared label set. The type and side label values are
determined by the messaging pattern.
| Label | Values | Description |
|---|---|---|
node | host name | The KubeMQ node that recorded the metric. |
client_id | client id | The connected client. Aggregated away on store series — the per-channel store collectors drop client_id at collect time, so queue, RPC-latency, and similar series carry only node, type, side, channel. |
type | events, events_store, commands, queries, queues | The messaging pattern. |
side | send, receive | Whether the metric is for the producing or consuming side of the channel. |
channel | channel name | The message channel the metric belongs to. |
Core messaging metrics
These collectors track message activity across all five patterns. They share the label set above.
| Prometheus name | Type | Description |
|---|---|---|
kubemq_messages_count | Counter | Total messages sent/received per channel. |
kubemq_messages_volume | Counter | Total byte volume per channel. |
kubemq_messages_last_seen | Gauge | Unix timestamp (ms) of last activity. |
kubemq_messages_delayed | Counter | Number of delayed queue messages. |
kubemq_messages_expired | Counter | Total expired queue messages. |
kubemq_messages_waiting | Gauge | Queue messages waiting for consumers. |
kubemq_clients_count | Gauge | Connected client count per channel. |
kubemq_errors_count | Counter | Total errors per channel. |
kubemq_messages_responses | Counter | Total RPC responses per channel. |
Queue health metrics
These series give queue operators visibility into redelivery, dead-letter dispositions,
backlog age, and dwell time. They use the standard four-label set (node, type, side,
channel) — client_id is aggregated away — except where a row notes an extra label.
| Prometheus name | Type | Description |
|---|---|---|
kubemq_queue_redelivery_total | Counter | Total queue redeliveries per channel — a receive whose post-increment receive count is greater than one — attributed to the source queue channel on the receive side. Uses the standard four labels only (no extra label). |
kubemq_queue_dlq_total | Counter | Total queue dead-letter dispositions per channel, attributed to the source channel on the receive side. Carries one extra reason label: routed (re-published to the configured dead-letter queue) or dropped (no DLQ configured or a marshal error — silent data loss made visible). The reason label is on dlq_total only, not on redelivery_total. |
kubemq_queue_backlog_age_seconds | Gauge | Age (seconds) of the oldest undelivered message in the backlog, per channel (queues/receive). A live gauge recomputed each 5-second snapshot cycle; 0 when the backlog is empty or fully delivered, and 0 after a restart until the next cycle rebuilds it. |
kubemq_queue_dwell_seconds_sum | Counter | Cumulative sum of per-message dwell times (seconds) on the receive side — the time from when a message entered the queue until it was delivered to a consumer. Survives restarts. Divide by kubemq_queue_dwell_messages_total for the average dwell. |
kubemq_queue_dwell_messages_total | Counter | Cumulative count of messages whose dwell time was recorded. Survives restarts. The denominator for the average dwell time. |
RPC latency metrics
These series measure command and query round-trip latency on the send side. They use the
standard four-label set.
| Prometheus name | Type | Description |
|---|---|---|
kubemq_rpc_latency_seconds_sum | Counter | Cumulative sum of RPC round-trip times (seconds) on the send side of a command or query channel — measured from request dispatch until the response is received. Survives restarts. Recorded only when a response is received (errored or timed-out requests with no response are excluded). Divide by kubemq_rpc_latency_calls_total for the average. |
kubemq_rpc_latency_calls_total | Counter | Cumulative count of RPC calls whose round-trip latency was recorded (type ∈ {commands, queries}, side = send). Survives restarts. The denominator for the average RPC latency. |
Cache-served queries are excluded. The query cache short-circuits before the latency is recorded, so these series measure real backend round-trips (cache misses), not local cache lookups. Commands have no cache and are always recorded.
Latency histograms
Three histogram instruments expose latency distributions (so you can compute percentiles
with histogram_quantile), labeled by node, type, and side.
| Prometheus name | Type | Description |
|---|---|---|
kubemq_rpc_latency_histogram_seconds | Histogram | RPC round-trip latency distribution (commands and queries, send side). Same gate as kubemq_rpc_latency_seconds_sum — recorded only when a response is received; cache-served queries are excluded. |
kubemq_queue_dwell_histogram_seconds | Histogram | Queue dwell-time distribution (queues, receive side). Its population matches kubemq_queue_dwell_messages_total. |
kubemq_operation_duration_seconds | Histogram | Per-operation send duration for patterns with no round-trip: type ∈ {events, events_store, queues} on the send side. Commands and queries use kubemq_rpc_latency_histogram_seconds for their percentile source. |
All three histograms share one bucket set (seconds), giving a consistent latency vocabulary
across /metrics:
0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60Cluster & infra metrics
These gauges expose node health, cluster role, and configured peer state, labeled by node
(and role where noted).
| Prometheus name | Type | Description |
|---|---|---|
kubemq_cluster_leader | Gauge | 1 if this node is the cluster leader or a standalone node (both act as the authoritative message processor); 0 otherwise. |
kubemq_cluster_role | Gauge | Info-gauge: emits 1 for the active role label only, 0 for the rest. role ∈ {leader, follower, candidate, standalone}. Filter with kubemq_cluster_role == 1. |
kubemq_cluster_ready | Gauge | 1 when the node is ready to accept traffic; 0 during startup or unhealthy states. |
kubemq_cluster_healthy | Gauge | 1 when the node is healthy. Distinct from ready — a node can be healthy but not yet ready. |
kubemq_cluster_state_seconds | Gauge | Seconds since the last cluster state change. For clustered nodes: seconds since the last ready-settle (leadership election or follower sync). For standalone nodes: seconds since server startup. |
kubemq_cluster_peers | Gauge | The configured bootstrap peer count, including self (minimum 1 for standalone). This is the configured bootstrap peer list, not live cluster membership — on a running cluster, live membership may differ during leader transitions. |
On a single-node (standalone) server, kubemq_cluster_leader = 1,
kubemq_cluster_role{role="standalone"} = 1, kubemq_cluster_ready = 1 once ready, and
kubemq_cluster_peers = 1. On a multi-node cluster, exactly one node has
kubemq_cluster_leader = 1 at any given time.
Agent-platform metrics
KubeMQ's agent platform emits its own series for MCP tool calls and A2A agent traffic. These use domain-specific labels rather than the core messaging label set.
| Prometheus name | Type | Labels | Description |
|---|---|---|---|
kubemq_mcp_tool_calls_total | Counter | tool, status | Total MCP tool calls. |
kubemq_mcp_tool_duration_seconds | Histogram | tool | Duration of MCP tool calls (seconds). |
kubemq_a2a_requests_total | Counter | agent_id, method, status | Total A2A requests routed to agents (any path — HTTP gateway and MCP bridge). |
kubemq_a2a_request_duration_seconds | Histogram | agent_id | Duration of A2A requests routed to agents (any path — HTTP gateway and MCP bridge). |
kubemq_a2a_errors_total | Counter | agent_id, error_code | Total A2A errors for requests routed to agents (any path — HTTP gateway and MCP bridge). |
kubemq_a2a_stream_events_total | Counter | agent_id | Total A2A stream events delivered to SSE clients (receive side). |
kubemq_a2a_stream_outcomes_total | Counter | agent_id, outcome | Total A2A streams by terminal outcome (done, error, idle_timeout, canceled) — exactly one per stream. |
kubemq_a2a_registry_operations_total | Counter | op, status | Total agent registry operations (register, deregister, heartbeat, expire). |
kubemq_a2a_sse_streams_active | Gauge | — | Current number of active A2A SSE streams. |
The MCP tool-call histogram (kubemq_mcp_tool_duration_seconds) uses the bucket set
0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10; the A2A request-duration histogram
(kubemq_a2a_request_duration_seconds) uses 0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60.
The agent_id label is bounded. The first ~1000 distinct agent IDs each get their own
label value; every subsequent agent ID collapses into agent_id="other". This is cardinality
protection — for exact per-agent leaderboards across the whole fleet, use the dashboard rather
than Prometheus.
The method label is sanitized. Each A2A method is checked against a fixed allowlist of
known methods; anything not in the list is recorded as method="unknown". This keeps a
malformed or malicious request stream from exploding Prometheus label cardinality.
In a cluster, these counters are aggregated across all nodes, so the totals reflect the whole deployment rather than a single replica.
PromQL examples
# RPC p99 latency (commands) — rolling 5-minute window
histogram_quantile(0.99,
rate(kubemq_rpc_latency_histogram_seconds_bucket{type="commands"}[5m])
)
# Queue dwell p95 across all nodes
histogram_quantile(0.95,
sum(rate(kubemq_queue_dwell_histogram_seconds_bucket[5m])) by (le)
)
# Alert: no leader exists across the cluster
sum(kubemq_cluster_leader) == 0
# Alert: a node has been not-ready for more than 60 seconds
kubemq_cluster_ready == 0 and kubemq_cluster_state_seconds > 60Grafana
Point Grafana at the Prometheus instance scraping KubeMQ and build dashboards on the series
above — message rates from kubemq_messages_count, queue health from the
kubemq_queue_* series, latency percentiles from the histogram buckets, and cluster state
from the kubemq_cluster_* gauges.
Internal channels
Internal cluster channels are filtered out of the user-facing metrics, so they never appear in the series above.
Was this page helpful?
Observability
Monitor KubeMQ end to end — Prometheus metrics, OpenTelemetry tracing, structured logs, an audit trail, the dashboard, and the management API on port 8080.
Distributed Tracing
Export OpenTelemetry traces and metrics over OTLP to Jaeger, Grafana Tempo, or Datadog — samplers, span attributes, and context propagation.