Skip to content

Add prometheus collector for delayed messages count - #17

Draft
LoisSotoLopez wants to merge 3 commits into
cloudamqp_mainfrom
delayed-messages-prometheus-metrics
Draft

Add prometheus collector for delayed messages count#17
LoisSotoLopez wants to merge 3 commits into
cloudamqp_mainfrom
delayed-messages-prometheus-metrics

Conversation

@LoisSotoLopez

Copy link
Copy Markdown

Proposed Changes

This PR provides a prometheus_collector for the plugin exposing just one gauge metric rabbitmq_detailed_delayed_messages under the delayed_messages_by_exchange family.

The metric represents the number of delayed messages (still not routed out of the delayed exchange) per exchange and vhost.

rabbitmq_detailed_delayed_messages{vhost="/",exchange="ex1"} 23
rabbitmq_detailed_delayed_messages{vhost="/",exchange="ex2"} 11

The metric is not returned cluster-aggregated i.e. collecting the metric in a node returns the number of delayed messages in that node, not in the whole cluster. To get the total number of messages delayed in a cluster a user would need to aggregate all returned values for the N nodes of the cluster.

Regarding the relationship with the Prometheus dependency, prometheus is set just as a build dependency so the plugin can be enabled without metrics.


-define(METRIC_NAME_PREFIX, "rabbitmq_detailed_").

-define(METRIC_FAMILY_DELAYED_MESSAGES, delayed_messages_by_exchange).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the family be something like delayed_exchange_metrics? like ra_metrics queue_coarse_metrics?

@the-mikedavis the-mikedavis left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's some room to use seshat for counters here too. With rabbitmq/seshat#17 we could show the total number of delayed messages on the node, summed between all delayed exchanges.

Comment on lines +143 to +144
is_vhost_enabled(VHost, VHostsFilter) ->
ordsets:is_element(VHost, VHostsFilter).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ordsets from upstream? This ought to be a sets v2 these days, eh? It would probably be a tough breaking change to make.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ordsets from upstream?

No, upstream builds a map, not an ordset, representing the vhost filter in prometheus_rabbitmq_core_metrics_collector:vhosts_filter_from_pdict . It does so to use the filter in some guards.

This ought to be a sets v2 these days, eh?

I used an ordset because AFAIR ordsets are the leanest type that is not a bare list. I think ordset, the upstream map, or a set v2 would be practically the same in our case, but ordset always feels the leanest option (smallest heap and no need to pass the v2 argument).

Comment on lines +120 to +135
lists:foldl(
fun(#resource{virtual_host = VHost} = XName, Acc) ->
case is_vhost_enabled(VHost, VHostsFilter) of
true ->
delayed_messages(XName, VHost, Acc);
false ->
Acc
end
end,
[],
rabbit_exchange:list_names()).

delayed_messages(#resource{name = Name} = XName, VHost, Acc) ->
case rabbit_exchange:lookup(XName) of
{ok, #exchange{type = ?EXCHANGE_TYPE} = X} ->
Count = rabbit_delayed_message:messages_delayed(X),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be handy to have a list_by_type in the server. Queue types already have helpers like that I believe. Maybe a nice contribution upstream!

@LoisSotoLopez

LoisSotoLopez commented Aug 7, 2026

Copy link
Copy Markdown
Author

I think there's some room to use seshat for counters here too. With rabbitmq/seshat#17 we could show the total number of delayed messages on the node, summed between all delayed exchanges.

@the-mikedavis A few thoughts around this idea.

The seshat:fold function (rabbitmq/seshat#17) is still not available so we would need to wait for merge, release and rmq bumping the dep pin.

Also, the current implementation enumerates live exchanges so we don't need any cleanup on exchange deletion. That would be needed if we used seshat counters.

On the other hand, the internal structure seshat uses feels more correct than the one I implemented. One ETS table plus few (probably just one) persistent term entries rather than one persistent term entry per new exchange. This is relevant bc each persistent term write copies its index table iirc.

Since I'm leaving today on vacations I'll commit one other thing I have almost ready (byte count in addition to message count), and let @gomoripeti make the final decision in my absence. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants