parent
9576aaf43c
commit
aef931f750
|
|
@ -371,6 +371,9 @@ end}.
|
|||
{datatype, {enum, [true, false]}}
|
||||
]}.
|
||||
|
||||
{mapping, "management.enable_queue_totals", "rabbitmq_management.enable_queue_totals", [
|
||||
{datatype, {enum, [true, false]}}]}.
|
||||
|
||||
%% ===========================================================================
|
||||
%% Authorization
|
||||
|
||||
|
|
|
|||
|
|
@ -151,7 +151,12 @@ var DISABLED_STATS_COLUMNS =
|
|||
['features', 'Features (with policy)', true],
|
||||
['features_no_policy', 'Features (no policy)', false],
|
||||
['policy', 'Policy', false],
|
||||
['state', 'State', true]]},
|
||||
['state', 'State', true]],
|
||||
'Messages': [['msgs-ready', 'Ready', true],
|
||||
['msgs-unacked', 'Unacknowledged', true],
|
||||
['msgs-ram', 'In memory', false],
|
||||
['msgs-persistent', 'Persistent', false],
|
||||
['msgs-total', 'Total', true]]},
|
||||
'connections':
|
||||
{'Overview': [['user', 'User name', true],
|
||||
['state', 'State', true]]},
|
||||
|
|
@ -653,6 +658,7 @@ function setup_global_vars() {
|
|||
exchange_types = overview.exchange_types;
|
||||
|
||||
disable_stats = overview.disable_stats;
|
||||
enable_queue_totals = overview.enable_queue_totals;
|
||||
COLUMNS = disable_stats?DISABLED_STATS_COLUMNS:ALL_COLUMNS;
|
||||
|
||||
setup_chart_ranges(overview.sample_retention_policies);
|
||||
|
|
|
|||
|
|
@ -9,12 +9,16 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<%= group_heading('queues', 'Overview', [vhosts_interesting, nodes_interesting, true]) %>
|
||||
<% if(!disable_stats) { %>
|
||||
<% if(disable_stats && enable_queue_totals) { %>
|
||||
<%= group_heading('queues', 'Messages', []) %>
|
||||
<% } else { %>
|
||||
<% if(!disable_stats) { %>
|
||||
<%= group_heading('queues', 'Messages', []) %>
|
||||
<%= group_heading('queues', 'Message bytes', []) %>
|
||||
<% if (rates_mode != 'none') { %>
|
||||
<%= group_heading('queues', 'Message rates', []) %>
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% } %>
|
||||
<th class="plus-minus"><span class="popup-options-link" title="Click to change columns" type="columns" for="queues">+/-</span></th>
|
||||
</tr>
|
||||
|
|
@ -47,7 +51,18 @@
|
|||
<% if (show_column('queues', 'state')) { %>
|
||||
<th><%= fmt_sort('State', 'state') %></th>
|
||||
<% } %>
|
||||
<% if(!disable_stats) { %>
|
||||
<% if(disable_stats && enable_queue_totals) { %>
|
||||
<% if (show_column('queues', 'msgs-ready')) { %>
|
||||
<th><%= fmt_sort('Ready', 'messages_ready') %></th>
|
||||
<% } %>
|
||||
<% if (show_column('queues', 'msgs-unacked')) { %>
|
||||
<th><%= fmt_sort('Unacked', 'messages_unacknowledged') %></th>
|
||||
<% } %>
|
||||
<% if (show_column('queues', 'msgs-total')) { %>
|
||||
<th><%= fmt_sort('Total', 'messages') %></th>
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% if(!disable_stats) { %>
|
||||
<% if (show_column('queues', 'msgs-ready')) { %>
|
||||
<th><%= fmt_sort('Ready', 'messages_ready') %></th>
|
||||
<% } %>
|
||||
|
|
@ -148,22 +163,28 @@
|
|||
<% if (show_column('queues', 'state')) { %>
|
||||
<td class="c"><%= fmt_object_state(queue) %></td>
|
||||
<% } %>
|
||||
<% if(!disable_stats) { %>
|
||||
<% if(!disable_stats || (disable_stats && enable_queue_totals)) { %>
|
||||
<% if (show_column('queues', 'msgs-ready')) { %>
|
||||
<td class="r"><%= fmt_num_thousands(queue.messages_ready) %></td>
|
||||
<% } %>
|
||||
<% if (show_column('queues', 'msgs-unacked')) { %>
|
||||
<td class="r"><%= fmt_num_thousands(queue.messages_unacknowledged) %></td>
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% if(!disable_stats) { %>
|
||||
<% if (show_column('queues', 'msgs-ram')) { %>
|
||||
<td class="r"><%= fmt_num_thousands(queue.messages_ram) %></td>
|
||||
<% } %>
|
||||
<% if (show_column('queues', 'msgs-persistent')) { %>
|
||||
<td class="r"><%= fmt_num_thousands(queue.messages_persistent) %></td>
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% if(!disable_stats || (disable_stats && enable_queue_totals)) { %>
|
||||
<% if (show_column('queues', 'msgs-total')) { %>
|
||||
<td class="r"><%= fmt_num_thousands(queue.messages) %></td>
|
||||
<% } %>
|
||||
<% } %>
|
||||
<% if(!disable_stats) { %>
|
||||
<% if (show_column('queues', 'msg-bytes-ready')) { %>
|
||||
<td class="r"><%= fmt_bytes(queue.message_bytes_ready) %></td>
|
||||
<% } %>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
-export([get_path_prefix/0]).
|
||||
-export([catch_no_such_user_or_vhost/2]).
|
||||
|
||||
-export([disable_stats/1]).
|
||||
-export([disable_stats/1, enable_queue_totals/1]).
|
||||
|
||||
-import(rabbit_misc, [pget/2]).
|
||||
|
||||
|
|
@ -133,6 +133,13 @@ disable_stats(ReqData) ->
|
|||
MgmtOnly orelse get_bool_env(rabbitmq_management, disable_management_stats, false)
|
||||
orelse get_bool_env(rabbitmq_management_agent, disable_metrics_collector, false).
|
||||
|
||||
enable_queue_totals(ReqData) ->
|
||||
EnableTotals = case qs_val(<<"enable_queue_totals">>, ReqData) of
|
||||
<<"true">> -> true;
|
||||
_ -> false
|
||||
end,
|
||||
EnableTotals orelse get_bool_env(rabbitmq_management, enable_queue_totals, false).
|
||||
|
||||
get_bool_env(Application, Par, Default) ->
|
||||
case application:get_env(Application, Par, Default) of
|
||||
true -> true;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ to_json(ReqData, Context = #context{user = User = #user{tags = Tags}}) ->
|
|||
{cluster_name, rabbit_nodes:cluster_name()},
|
||||
{erlang_version, erlang_version()},
|
||||
{erlang_full_version, erlang_full_version()},
|
||||
{disable_stats, rabbit_mgmt_util:disable_stats(ReqData)}],
|
||||
{disable_stats, rabbit_mgmt_util:disable_stats(ReqData)},
|
||||
{enable_queue_totals, rabbit_mgmt_util:enable_queue_totals(ReqData)}],
|
||||
try
|
||||
case rabbit_mgmt_util:disable_stats(ReqData) of
|
||||
false ->
|
||||
|
|
|
|||
|
|
@ -73,9 +73,16 @@ basic(ReqData) ->
|
|||
[rabbit_mgmt_format:queue(amqqueue:set_state(Q, down)) ||
|
||||
Q <- down_queues(ReqData)];
|
||||
true ->
|
||||
[rabbit_mgmt_format:queue(Q) ++ policy(Q) || Q <- queues0(ReqData)] ++
|
||||
[rabbit_mgmt_format:queue(amqqueue:set_state(Q, down)) ||
|
||||
Q <- down_queues(ReqData)]
|
||||
case rabbit_mgmt_util:enable_queue_totals(ReqData) of
|
||||
false ->
|
||||
[rabbit_mgmt_format:queue(Q) ++ policy(Q) || Q <- queues0(ReqData)] ++
|
||||
[rabbit_mgmt_format:queue(amqqueue:set_state(Q, down)) ||
|
||||
Q <- down_queues(ReqData)];
|
||||
true ->
|
||||
[rabbit_mgmt_format:queue_info(Q) || Q <- queues_with_totals(ReqData)] ++
|
||||
[rabbit_mgmt_format:queue(amqqueue:set_state(Q, down)) ||
|
||||
Q <- down_queues(ReqData)]
|
||||
end
|
||||
end.
|
||||
|
||||
augmented(ReqData, Context) ->
|
||||
|
|
@ -99,6 +106,12 @@ basic_vhost_filtered(ReqData, Context) ->
|
|||
queues0(ReqData) ->
|
||||
rabbit_mgmt_util:all_or_one_vhost(ReqData, fun rabbit_amqqueue:list/1).
|
||||
|
||||
queues_with_totals(ReqData) ->
|
||||
rabbit_mgmt_util:all_or_one_vhost(ReqData, fun collect_info_all/1).
|
||||
|
||||
collect_info_all(VHostPath) ->
|
||||
rabbit_amqqueue:collect_info_all(VHostPath, [name, durable, auto_delete, exclusive, owner_pid, arguments, type, state, policy, totals, type_specific]).
|
||||
|
||||
down_queues(ReqData) ->
|
||||
rabbit_mgmt_util:all_or_one_vhost(ReqData, fun rabbit_amqqueue:list_down/1).
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,8 @@ all_tests() -> [
|
|||
samples_range_test,
|
||||
sorting_test,
|
||||
columns_test,
|
||||
if_empty_unused_test].
|
||||
if_empty_unused_test,
|
||||
queues_enable_totals_test].
|
||||
|
||||
%% -------------------------------------------------------------------
|
||||
%% Testsuite setup/teardown.
|
||||
|
|
@ -187,6 +188,10 @@ end_per_testcase(Testcase, Config) ->
|
|||
Config1 = end_per_testcase0(Testcase, Config),
|
||||
rabbit_ct_helpers:testcase_finished(Config1, Testcase).
|
||||
|
||||
end_per_testcase0(Testcase = queues_enable_totals_test, Config) ->
|
||||
rabbit_ct_broker_helpers:rpc(Config, 0, application, unset_env,
|
||||
[rabbitmq_management, enable_queue_totals]),
|
||||
rabbit_ct_helpers:testcase_finished(Config, Testcase);
|
||||
end_per_testcase0(Testcase = queues_test, Config) ->
|
||||
rabbit_ct_broker_helpers:delete_vhost(Config, <<"downvhost">>),
|
||||
rabbit_ct_helpers:testcase_finished(Config, Testcase);
|
||||
|
|
@ -438,6 +443,7 @@ queues_test(Config) ->
|
|||
leader => NodeBin,
|
||||
members => [NodeBin]}, Queue),
|
||||
|
||||
?assert(not maps:is_key(messages, Queue)),
|
||||
?assert(not maps:is_key(message_stats, Queue)),
|
||||
?assert(not maps:is_key(messages_details, Queue)),
|
||||
?assert(not maps:is_key(reductions_details, Queue)),
|
||||
|
|
@ -454,6 +460,87 @@ queues_test(Config) ->
|
|||
http_delete(Config, "/queues/downvhost/bar", {group, '2xx'}),
|
||||
passed.
|
||||
|
||||
queues_enable_totals_test(Config) ->
|
||||
rabbit_ct_broker_helpers:rpc(Config, 0, application, set_env,
|
||||
[rabbitmq_management, enable_queue_totals, true]),
|
||||
|
||||
Good = [{durable, true}],
|
||||
GoodQQ = [{durable, true}, {arguments, [{'x-queue-type', 'quorum'}]}],
|
||||
http_get(Config, "/queues/%2F/foo", ?NOT_FOUND),
|
||||
http_put(Config, "/queues/%2F/foo", GoodQQ, {group, '2xx'}),
|
||||
|
||||
Policy = [{pattern, <<"baz">>},
|
||||
{definition, [{<<"ha-mode">>, <<"all">>}]}],
|
||||
http_put(Config, "/policies/%2F/HA", Policy, {group, '2xx'}),
|
||||
http_put(Config, "/queues/%2F/baz", Good, {group, '2xx'}),
|
||||
|
||||
{Conn, Ch} = open_connection_and_channel(Config),
|
||||
Publish = fun(Q) ->
|
||||
amqp_channel:call(
|
||||
Ch, #'basic.publish'{exchange = <<"">>,
|
||||
routing_key = Q},
|
||||
#amqp_msg{payload = <<"message">>})
|
||||
end,
|
||||
Publish(<<"baz">>),
|
||||
Publish(<<"foo">>),
|
||||
Publish(<<"foo">>),
|
||||
|
||||
Fun = fun() ->
|
||||
length(rabbit_ct_broker_helpers:rpc(Config, 0, ets, tab2list,
|
||||
[queue_coarse_metrics])) == 2
|
||||
end,
|
||||
wait_until(Fun, 60),
|
||||
|
||||
Queues = http_get(Config, "/queues/%2F"),
|
||||
Queue = http_get(Config, "/queues/%2F/foo"),
|
||||
|
||||
Node = rabbit_ct_broker_helpers:get_node_config(Config, 0, nodename),
|
||||
NodeBin = atom_to_binary(Node, utf8),
|
||||
assert_list([#{name => <<"baz">>,
|
||||
vhost => <<"/">>,
|
||||
durable => true,
|
||||
auto_delete => false,
|
||||
exclusive => false,
|
||||
arguments => #{},
|
||||
node => NodeBin,
|
||||
slave_nodes => [],
|
||||
messages => 1,
|
||||
messages_ready => 1,
|
||||
messages_unacknowledged => 0,
|
||||
synchronised_slave_nodes => []},
|
||||
#{name => <<"foo">>,
|
||||
vhost => <<"/">>,
|
||||
durable => true,
|
||||
auto_delete => false,
|
||||
exclusive => null,
|
||||
arguments => #{'x-queue-type' => <<"quorum">>},
|
||||
leader => NodeBin,
|
||||
messages => 2,
|
||||
messages_ready => 2,
|
||||
messages_unacknowledged => 0,
|
||||
members => [NodeBin]}], Queues),
|
||||
assert_item(#{name => <<"foo">>,
|
||||
vhost => <<"/">>,
|
||||
durable => true,
|
||||
auto_delete => false,
|
||||
exclusive => false,
|
||||
arguments => #{'x-queue-type' => <<"quorum">>},
|
||||
leader => NodeBin,
|
||||
members => [NodeBin]}, Queue),
|
||||
|
||||
?assert(not maps:is_key(messages, Queue)),
|
||||
?assert(not maps:is_key(messages_ready, Queue)),
|
||||
?assert(not maps:is_key(messages_unacknowledged, Queue)),
|
||||
?assert(not maps:is_key(message_stats, Queue)),
|
||||
?assert(not maps:is_key(messages_details, Queue)),
|
||||
?assert(not maps:is_key(reductions_details, Queue)),
|
||||
|
||||
http_delete(Config, "/queues/%2F/foo", {group, '2xx'}),
|
||||
http_delete(Config, "/queues/%2F/baz", {group, '2xx'}),
|
||||
close_connection(Conn),
|
||||
|
||||
passed.
|
||||
|
||||
mirrored_queues_test(Config) ->
|
||||
Policy = [{pattern, <<".*">>},
|
||||
{definition, [{<<"ha-mode">>, <<"all">>}]}],
|
||||
|
|
|
|||
Loading…
Reference in New Issue