Display container-id in the UI and CLI

This commit is contained in:
David Ansari 2024-09-13 11:49:35 +02:00
parent 35fb30f331
commit f78f14ab1d
11 changed files with 69 additions and 55 deletions

View File

@ -37,6 +37,7 @@
[pid,
frame_max,
timeout,
container_id,
vhost,
user,
node

View File

@ -35,6 +35,7 @@
-record(v1_connection,
{name :: binary(),
container_id :: none | binary(),
vhost :: none | rabbit_types:vhost(),
%% server host
host :: inet:ip_address() | inet:hostname(),
@ -104,6 +105,7 @@ unpack_from_0_9_1(
connection_state = received_amqp3100,
connection = #v1_connection{
name = ConnectionName,
container_id = none,
vhost = none,
host = Host,
peer_host = PeerHost,
@ -491,6 +493,7 @@ handle_connection_frame(
end,
State1 = State0#v1{connection_state = running,
connection = Connection#v1_connection{
container_id = ContainerId,
vhost = Vhost,
incoming_max_frame_size = IncomingMaxFrameSize,
outgoing_max_frame_size = OutgoingMaxFrameSize,
@ -969,6 +972,8 @@ i(connected_at, #v1{connection = #v1_connection{connected_at = Val}}) ->
Val;
i(name, #v1{connection = #v1_connection{name = Val}}) ->
Val;
i(container_id, #v1{connection = #v1_connection{container_id = Val}}) ->
Val;
i(vhost, #v1{connection = #v1_connection{vhost = Val}}) ->
Val;
i(host, #v1{connection = #v1_connection{host = Val}}) ->

View File

@ -25,9 +25,9 @@
node_listeners/1, node_client_listeners/1,
register_connection/1, unregister_connection/1,
register_non_amqp_connection/1, unregister_non_amqp_connection/1,
connections/0, non_amqp_connections/0, connection_info_keys/0,
connection_info/1, connection_info/2,
connection_info_all/0, connection_info_all/1,
connections/0, non_amqp_connections/0,
connection_info/2,
connection_info_all/1,
emit_connection_info_all/4, emit_connection_info_local/3,
close_connection/2, close_connections/2, close_all_connections/1,
close_all_user_connections/2,
@ -482,23 +482,11 @@ non_amqp_connections() ->
local_non_amqp_connections() ->
pg_local:get_members(rabbit_non_amqp_connections).
-spec connection_info_keys() -> rabbit_types:info_keys().
connection_info_keys() -> rabbit_reader:info_keys().
-spec connection_info(rabbit_types:connection()) -> rabbit_types:infos().
connection_info(Pid) -> rabbit_reader:info(Pid).
-spec connection_info(rabbit_types:connection(), rabbit_types:info_keys()) ->
rabbit_types:infos().
connection_info(Pid, Items) -> rabbit_reader:info(Pid, Items).
-spec connection_info_all() -> [rabbit_types:infos()].
connection_info_all() -> cmap(fun (Q) -> connection_info(Q) end).
-spec connection_info_all(rabbit_types:info_keys()) ->
[rabbit_types:infos()].

View File

@ -43,7 +43,7 @@
-include_lib("rabbit_common/include/rabbit_framing.hrl").
-include_lib("rabbit_common/include/rabbit.hrl").
-export([start_link/2, info_keys/0, info/1, info/2, force_event_refresh/2,
-export([start_link/2, info/2, force_event_refresh/2,
shutdown/2]).
-export([system_continue/3, system_terminate/4, system_code_change/4]).
@ -116,10 +116,6 @@
connection_blocked_message_sent
}).
-define(STATISTICS_KEYS, [pid, recv_oct, recv_cnt, send_oct, send_cnt,
send_pend, state, channels, reductions,
garbage_collection]).
-define(SIMPLE_METRICS, [pid, recv_oct, send_oct, reductions]).
-define(OTHER_METRICS, [recv_cnt, send_cnt, send_pend, state, channels,
garbage_collection]).
@ -132,8 +128,6 @@
timeout, frame_max, channel_max, client_properties, connected_at,
node, user_who_performed_action]).
-define(INFO_KEYS, ?CREATION_EVENT_KEYS ++ ?STATISTICS_KEYS -- [pid]).
-define(AUTH_NOTIFICATION_INFO_KEYS,
[host, name, peer_host, peer_port, protocol, auth_mechanism,
ssl, ssl_protocol, ssl_cipher, peer_cert_issuer, peer_cert_subject,
@ -188,15 +182,6 @@ system_terminate(Reason, _Parent, _Deb, _State) ->
system_code_change(Misc, _Module, _OldVsn, _Extra) ->
{ok, Misc}.
-spec info_keys() -> rabbit_types:info_keys().
info_keys() -> ?INFO_KEYS.
-spec info(pid()) -> rabbit_types:infos().
info(Pid) ->
gen_server:call(Pid, info, infinity).
-spec info(pid(), rabbit_types:info_keys()) -> rabbit_types:infos().
info(Pid, Items) ->
@ -633,9 +618,6 @@ handle_other({'$gen_call', From, {shutdown, Explanation}}, State) ->
force -> stop;
normal -> NewState
end;
handle_other({'$gen_call', From, info}, State) ->
gen_server:reply(From, infos(?INFO_KEYS, State)),
State;
handle_other({'$gen_call', From, {info, Items}}, State) ->
gen_server:reply(From, try {ok, infos(Items, State)}
catch Error -> {error, Error}
@ -1627,6 +1609,7 @@ ic(client_properties, #connection{client_properties = CP}) -> CP;
ic(auth_mechanism, #connection{auth_mechanism = none}) -> none;
ic(auth_mechanism, #connection{auth_mechanism = {Name, _Mod}}) -> Name;
ic(connected_at, #connection{connected_at = T}) -> T;
ic(container_id, _) -> ''; % AMQP 1.0 specific field
ic(Item, #connection{}) -> throw({bad_argument, Item}).
socket_info(Get, Select, #v1{sock = Sock}) ->

View File

@ -1662,18 +1662,19 @@ events(Config) ->
Protocol = {protocol, {1, 0}},
AuthProps = [{name, <<"guest">>},
{auth_mechanism, <<"PLAIN">>},
{ssl, false},
Protocol],
{auth_mechanism, <<"PLAIN">>},
{ssl, false},
Protocol],
?assertMatch(
{value, _},
find_event(user_authentication_success, AuthProps, Events)),
{value, _},
find_event(user_authentication_success, AuthProps, Events)),
Node = get_node_config(Config, 0, nodename),
ConnectionCreatedProps = [Protocol,
{node, Node},
{vhost, <<"/">>},
{user, <<"guest">>},
{container_id, <<"my container">>},
{type, network}],
{value, ConnectionCreatedEvent} = find_event(
connection_created,
@ -1694,8 +1695,8 @@ events(Config) ->
Pid,
ClientProperties],
?assertMatch(
{value, _},
find_event(connection_closed, ConnectionClosedProps, Events)),
{value, _},
find_event(connection_closed, ConnectionClosedProps, Events)),
ok.
sync_get_unsettled_classic_queue(Config) ->
@ -3696,8 +3697,12 @@ list_connections(Config) ->
[ok = rabbit_ct_client_helpers:close_channels_and_connection(Config, Node) || Node <- [0, 1, 2]],
Connection091 = rabbit_ct_client_helpers:open_unmanaged_connection(Config, 0),
{ok, C0} = amqp10_client:open_connection(connection_config(0, Config)),
{ok, C2} = amqp10_client:open_connection(connection_config(2, Config)),
ContainerId0 = <<"ID 0">>,
ContainerId2 = <<"ID 2">>,
Cfg0 = maps:put(container_id, ContainerId0, connection_config(0, Config)),
Cfg2 = maps:put(container_id, ContainerId2, connection_config(2, Config)),
{ok, C0} = amqp10_client:open_connection(Cfg0),
{ok, C2} = amqp10_client:open_connection(Cfg2),
receive {amqp10_event, {connection, C0, opened}} -> ok
after 5000 -> ct:fail({missing_event, ?LINE})
end,
@ -3705,8 +3710,8 @@ list_connections(Config) ->
after 5000 -> ct:fail({missing_event, ?LINE})
end,
{ok, StdOut} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["list_connections", "--silent", "protocol"]),
Protocols0 = re:split(StdOut, <<"\n">>, [trim]),
{ok, StdOut0} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["list_connections", "--silent", "protocol"]),
Protocols0 = re:split(StdOut0, <<"\n">>, [trim]),
%% Remove any whitespaces.
Protocols1 = [binary:replace(Subject, <<" ">>, <<>>, [global]) || Subject <- Protocols0],
Protocols = lists:sort(Protocols1),
@ -3715,6 +3720,13 @@ list_connections(Config) ->
<<"{1,0}">>],
Protocols),
%% CLI should list AMQP 1.0 container-id
{ok, StdOut1} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["list_connections", "--silent", "container_id"]),
ContainerIds0 = re:split(StdOut1, <<"\n">>, [trim]),
ContainerIds = lists:sort(ContainerIds0),
?assertEqual([<<>>, ContainerId0, ContainerId2],
ContainerIds),
ok = rabbit_ct_client_helpers:close_connection(Connection091),
ok = close_connection_sync(C0),
ok = close_connection_sync(C2).
@ -6021,8 +6033,8 @@ find_event(Type, Props, Events) when is_list(Props), is_list(Events) ->
fun(#event{type = EventType, props = EventProps}) ->
Type =:= EventType andalso
lists:all(
fun({Key, _Value}) ->
lists:keymember(Key, 1, EventProps)
fun(Prop) ->
lists:member(Prop, EventProps)
end, Props)
end, Events).

View File

@ -96,7 +96,7 @@ disconnect_detected_during_alarm(Config) ->
ListConnections =
fun() ->
rpc:call(A, rabbit_networking, connection_info_all, [])
rpc:call(A, rabbit_networking, connection_info_all, [[state]])
end,
%% We've already disconnected, but blocked connection still should still linger on.

View File

@ -17,7 +17,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListConnectionsCommand do
@info_keys ~w(pid name port host peer_port peer_host ssl ssl_protocol
ssl_key_exchange ssl_cipher ssl_hash peer_cert_subject
peer_cert_issuer peer_cert_validity state
channels protocol auth_mechanism user vhost timeout frame_max
channels protocol auth_mechanism user vhost container_id timeout frame_max
channel_max client_properties recv_oct recv_cnt send_oct
send_cnt send_pend connected_at)a
@ -79,7 +79,7 @@ defmodule RabbitMQ.CLI.Ctl.Commands.ListConnectionsCommand do
def help_section(), do: :observability_and_health_checks
def description(), do: "Lists AMQP 0.9.1 connections for the node"
def description(), do: "Lists AMQP connections for the node"
def banner(_, _), do: "Listing connections ..."
end

View File

@ -108,7 +108,8 @@ var ALL_COLUMNS =
['rate-redeliver', 'redelivered', false],
['rate-ack', 'ack', true]]},
'connections':
{'Overview': [['user', 'User name', true],
{'Overview': [['container_id', 'Container ID', true],
['user', 'User name', true],
['state', 'State', true]],
'Details': [['ssl', 'TLS', true],
['ssl_info', 'TLS details', false],
@ -585,7 +586,10 @@ var HELP = {
<dd>Rate at which queues are created. Declaring a queue that already exists counts for a "Declared" event, but not for a "Created" event. </dd>\
<dt>Deleted</dt>\
<dd>Rate at which queues are deleted.</dd>\
</dl> '
</dl> ',
'container-id':
'Name of the client application as sent from client to RabbitMQ in field container-id of the AMQP 1.0 <a target="_blank" href="https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-open">open</a> frame.'
};

View File

@ -17,11 +17,20 @@
<% if (connection.client_properties.connection_name) { %>
<tr>
<th>Client-provided name</th>
<th>Client-provided connection name</th>
<td><%= fmt_string(connection.client_properties.connection_name) %></td>
</tr>
<% } %>
<% if (connection.container_id) { %>
<tr>
<th>Container ID
<span class="help" id="container-id"></span>
</th>
<td><%= fmt_string(connection.container_id) %></td>
</tr>
<% } %>
<tr>
<th>Username</th>
<td><%= fmt_string(connection.user) %></td>

View File

@ -26,6 +26,9 @@
<% if (nodes_interesting) { %>
<th><%= fmt_sort('Node', 'node') %></th>
<% } %>
<% if (show_column('connections', 'container_id')) { %>
<th>Container ID <span class="help" id="container-id"></span></th>
<% } %>
<% if (show_column('connections', 'user')) { %>
<th><%= fmt_sort('User name', 'user') %></th>
<% } %>
@ -84,7 +87,9 @@
<% if(connection.client_properties) { %>
<td>
<%= link_conn(connection.name) %>
<sub><%= fmt_string(short_conn(connection.client_properties.connection_name)) %></sub>
<% if (connection.client_properties.connection_name) { %>
<sub><%= fmt_string(short_conn(connection.client_properties.connection_name)) %></sub>
<% } %>
</td>
<% } else { %>
<td><%= link_conn(connection.name) %></td>
@ -92,6 +97,13 @@
<% if (nodes_interesting) { %>
<td><%= fmt_node(connection.node) %></td>
<% } %>
<% if (show_column('connections', 'container_id')) { %>
<td class="c">
<% if (connection.container_id) { %>
<%= fmt_string(connection.container_id) %>
<% } %>
</td>
<% } %>
<% if (show_column('connections', 'user')) { %>
<td class="c"><%= fmt_string(connection.user) %></td>
<% } %>

View File

@ -17,7 +17,7 @@
<% if (connection.client_properties.connection_name) { %>
<tr>
<th>Client-provided name</th>
<th>Client-provided connection name</th>
<td><%= fmt_string(connection.client_properties.connection_name) %></td>
</tr>
<% } %>