Skip to content

Commit 2a93bbc

Browse files
authored
RMQ-1460: Emit queue_info metric (#13583)
To allow filtering on queue type or membership status, we need an info metric for queues; see https://grafana.com/blog/2021/08/04/how-to-use-promql-joins-for-more-effective-queries-of-prometheus-metrics-at-scale/#info-metrics With this change, per-object metrics and the detailed metrics (if queue-related families are requested) will contain rabbitmq_queue_info / rabbitmq_detailed_queue_info with a value of 1 and labels including the queue name, vhost, queue type and membership status.
1 parent c151806 commit 2a93bbc

File tree

2 files changed

+113
-10
lines changed

2 files changed

+113
-10
lines changed

deps/rabbitmq_prometheus/src/collectors/prometheus_rabbitmq_core_metrics_collector.erl

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,14 +301,25 @@ register() ->
301301
deregister_cleanup(_) -> ok.
302302

303303
collect_mf('detailed', Callback) ->
304-
collect(true, ?DETAILED_METRIC_NAME_PREFIX, vhosts_filter_from_pdict(), enabled_mfs_from_pdict(?METRICS_RAW), Callback),
304+
IncludedMFs = enabled_mfs_from_pdict(?METRICS_RAW),
305+
collect(true, ?DETAILED_METRIC_NAME_PREFIX, vhosts_filter_from_pdict(), IncludedMFs, Callback),
305306
collect(true, ?CLUSTER_METRIC_NAME_PREFIX, vhosts_filter_from_pdict(), enabled_mfs_from_pdict(?METRICS_CLUSTER), Callback),
307+
%% the detailed endpoint should emit queue_info only if queue metrics were requested
308+
MFs = proplists:get_keys(IncludedMFs),
309+
case lists:member(queue_coarse_metrics, MFs) orelse
310+
lists:member(queue_consumer_count, MFs) orelse
311+
lists:member(queue_metrics, MFs) of
312+
true ->
313+
emit_queue_info(?DETAILED_METRIC_NAME_PREFIX, vhosts_filter_from_pdict(), Callback);
314+
false -> ok
315+
end,
306316
%% identity is here to enable filtering on a cluster name (as already happens in existing dashboards)
307317
emit_identity_info(<<"detailed">>, Callback),
308318
ok;
309319
collect_mf('per-object', Callback) ->
310320
collect(true, ?METRIC_NAME_PREFIX, false, ?METRICS_RAW, Callback),
311321
totals(Callback),
322+
emit_queue_info(?METRIC_NAME_PREFIX, false, Callback),
312323
emit_identity_info(<<"per-object">>, Callback),
313324
ok;
314325
collect_mf('memory-breakdown', Callback) ->
@@ -406,6 +417,62 @@ identity_info(Endpoint) ->
406417
}]
407418
}.
408419

420+
membership(Pid, Members) when is_pid(Pid) ->
421+
case node(Pid) =:= node() of
422+
true ->
423+
case is_process_alive(Pid) of
424+
true -> leader;
425+
false -> undefined
426+
end;
427+
false ->
428+
case lists:member(node(), Members) of
429+
true -> follower;
430+
false -> not_a_member
431+
end
432+
end;
433+
membership({Name, Node}, Members) ->
434+
case Node =:= node() of
435+
true ->
436+
case is_process_alive(whereis(Name)) of
437+
true -> leader;
438+
false -> undefined
439+
end;
440+
false ->
441+
case lists:member(node(), Members) of
442+
true -> follower;
443+
false -> not_a_member
444+
end
445+
end;
446+
membership(_, _Members) ->
447+
undefined.
448+
449+
emit_queue_info(Prefix, VHostsFilter, Callback) ->
450+
Help = <<"A metric with a constant '1' value and labels that provide some queue details">>,
451+
QInfos = lists:foldl(
452+
fun(Q, Acc) ->
453+
#resource{virtual_host = VHost, name = Name} = amqqueue:get_name(Q),
454+
case is_map(VHostsFilter) andalso maps:get(VHost, VHostsFilter) == false of
455+
true -> Acc;
456+
false ->
457+
Type = amqqueue:get_type(Q),
458+
TypeState = amqqueue:get_type_state(Q),
459+
Members = maps:get(nodes, TypeState, []),
460+
case membership(amqqueue:get_pid(Q), Members) of
461+
not_a_member ->
462+
Acc;
463+
Membership ->
464+
QInfo = [
465+
{vhost, VHost},
466+
{queue, Name},
467+
{queue_type, Type},
468+
{membership, Membership}
469+
],
470+
[{QInfo, 1}|Acc]
471+
end
472+
end
473+
end, [], rabbit_amqqueue:list()),
474+
Callback(prometheus_model_helpers:create_mf(<<Prefix/binary, "queue_info">>, Help, gauge, QInfos)).
475+
409476
add_metric_family({Name, Type, Help, Metrics}, Callback) ->
410477
MN = <<?METRIC_NAME_PREFIX/binary, (prometheus_model_helpers:metric_name(Name))/binary>>,
411478
Callback(create_mf(MN, Help, Type, Metrics)).
@@ -890,4 +957,3 @@ vhosts_filter_from_pdict() ->
890957
Enabled = maps:from_list([ {VHost, true} || VHost <- L ]),
891958
maps:merge(All, Enabled)
892959
end.
893-

deps/rabbitmq_prometheus/test/rabbit_prometheus_http_SUITE.erl

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -533,19 +533,56 @@ queue_consumer_count_single_vhost_per_object_test(Config) ->
533533

534534
%% There should be exactly 2 metrics returned (2 queues in that vhost, `queue_consumer_count` has only single metric)
535535
?assertEqual(#{rabbitmq_detailed_queue_consumers =>
536-
#{#{queue => "vhost-1-queue-with-consumer",vhost => "vhost-1"} => [1],
537-
#{queue => "vhost-1-queue-with-messages",vhost => "vhost-1"} => [0]}},
536+
#{#{queue => "vhost-1-queue-with-consumer",vhost => "vhost-1"} => [1],
537+
#{queue => "vhost-1-queue-with-messages",vhost => "vhost-1"} => [0]},
538+
rabbitmq_detailed_queue_info =>
539+
#{#{queue => "vhost-1-queue-with-consumer",
540+
vhost => "vhost-1",
541+
queue_type => "rabbit_classic_queue",
542+
membership => "leader"} => [1],
543+
#{queue => "vhost-1-queue-with-messages",
544+
vhost => "vhost-1",
545+
queue_type => "rabbit_classic_queue",
546+
membership => "leader"} => [1]}
547+
},
538548
parse_response(Body)),
539549
ok.
540550

541551
queue_consumer_count_all_vhosts_per_object_test(Config) ->
542552
Expected = #{rabbitmq_detailed_queue_consumers =>
543-
#{#{queue => "vhost-1-queue-with-consumer",vhost => "vhost-1"} => [1],
544-
#{queue => "vhost-1-queue-with-messages",vhost => "vhost-1"} => [0],
545-
#{queue => "vhost-2-queue-with-consumer",vhost => "vhost-2"} => [1],
546-
#{queue => "vhost-2-queue-with-messages",vhost => "vhost-2"} => [0],
547-
#{queue => "default-queue-with-consumer",vhost => "/"} => [1],
548-
#{queue => "default-queue-with-messages",vhost => "/"} => [0]}},
553+
#{#{queue => "vhost-1-queue-with-consumer",vhost => "vhost-1"} => [1],
554+
#{queue => "vhost-1-queue-with-messages",vhost => "vhost-1"} => [0],
555+
#{queue => "vhost-2-queue-with-consumer",vhost => "vhost-2"} => [1],
556+
#{queue => "vhost-2-queue-with-messages",vhost => "vhost-2"} => [0],
557+
#{queue => "default-queue-with-consumer",vhost => "/"} => [1],
558+
#{queue => "default-queue-with-messages",vhost => "/"} => [0]},
559+
560+
rabbitmq_detailed_queue_info =>
561+
#{#{queue => "default-queue-with-consumer",
562+
vhost => "/",
563+
queue_type => "rabbit_classic_queue",
564+
membership => "leader"} => [1],
565+
#{queue => "default-queue-with-messages",
566+
vhost => "/",
567+
queue_type => "rabbit_classic_queue",
568+
membership => "leader"} => [1],
569+
#{queue => "vhost-1-queue-with-consumer",
570+
vhost => "vhost-1",
571+
queue_type => "rabbit_classic_queue",
572+
membership => "leader"} => [1],
573+
#{queue => "vhost-1-queue-with-messages",
574+
vhost => "vhost-1",
575+
queue_type => "rabbit_classic_queue",
576+
membership => "leader"} => [1],
577+
#{queue => "vhost-2-queue-with-consumer",
578+
vhost => "vhost-2",
579+
queue_type => "rabbit_classic_queue",
580+
membership => "leader"} => [1],
581+
#{queue => "vhost-2-queue-with-messages",
582+
vhost => "vhost-2",
583+
queue_type => "rabbit_classic_queue",
584+
membership => "leader"} => [1]}
585+
},
549586

550587
%% No vhost given, all should be returned
551588
{_, Body1} = http_get_with_pal(Config, "/metrics/detailed?family=queue_consumer_count&per-object=1", [], 200),

0 commit comments

Comments
 (0)