Skip to content

Commit bc26af4

Browse files
committed
WIP List sessions for connection
Display session and link details on the connection page in the Management UI. Example query: ``` curl -u guest:guest 'http://localhost:15672/api/connections/%5B%3A%3A1%5D%3A49564%20-%3E%20%5B%3A%3A1%5D%3A5672/sessions' | jq . ```
1 parent 033a793 commit bc26af4

File tree

8 files changed

+181
-3
lines changed

8 files changed

+181
-3
lines changed

deps/rabbit/src/rabbit_amqp_reader.erl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,8 @@ silent_close_delay() ->
967967
-spec info(rabbit_types:connection(), rabbit_types:info_keys()) ->
968968
rabbit_types:infos().
969969
info(Pid, InfoItems) ->
970-
case InfoItems -- ?INFO_ITEMS of
970+
KnownItems = [sessions | ?INFO_ITEMS],
971+
case InfoItems -- KnownItems of
971972
[] ->
972973
case gen_server:call(Pid, {info, InfoItems}, infinity) of
973974
{ok, InfoList} ->
@@ -1065,6 +1066,8 @@ i(client_properties, #v1{connection = #v1_connection{properties = Props}}) ->
10651066
end;
10661067
i(channels, #v1{tracked_channels = Channels}) ->
10671068
maps:size(Channels);
1069+
i(sessions, #v1{tracked_channels = Val}) ->
1070+
Val;
10681071
i(channel_max, #v1{connection = #v1_connection{channel_max = Max}}) ->
10691072
Max;
10701073
i(reductions = Item, _State) ->

deps/rabbit/src/rabbit_amqp_session.erl

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@
9292
conserve_resources/3,
9393
check_resource_access/4,
9494
check_read_permitted_on_topic/4,
95-
reset_authz/2
95+
reset_authz/2,
96+
info/1
9697
]).
9798

9899
-export([init/1,
@@ -490,6 +491,8 @@ conserve_resources(Pid, Source, {_, Conserve, _}) ->
490491
reset_authz(Pid, User) ->
491492
gen_server:cast(Pid, {reset_authz, User}).
492493

494+
handle_call(infos, _From, State) ->
495+
reply(infos(State), State);
493496
handle_call(Msg, _From, State) ->
494497
Reply = {error, {not_understood, Msg}},
495498
reply(Reply, State).
@@ -3702,6 +3705,32 @@ format_status(
37023705
topic_permission_cache => TopicPermissionCache},
37033706
maps:update(state, State, Status).
37043707

3708+
-spec info(pid()) ->
3709+
{ok, rabbit_types:infos()} | {error, term()}.
3710+
info(Pid) ->
3711+
try gen_server:call(Pid, infos) of
3712+
Infos ->
3713+
{ok, Infos}
3714+
catch exit:timeout ->
3715+
{error, timeout}
3716+
end.
3717+
3718+
infos(#state{cfg = #cfg{channel_num = ChannelNum},
3719+
incoming_window = IncomingWindow,
3720+
incoming_links = IncomingLinks,
3721+
outgoing_links = OutgoingLinks}) ->
3722+
[
3723+
{channel_number, ChannelNum},
3724+
{incoming_window, IncomingWindow},
3725+
{incoming_links, info_incoming_links(IncomingLinks)}
3726+
].
3727+
3728+
info_incoming_links(Links) ->
3729+
[[
3730+
{handle, Handle},
3731+
{snd_settle_mode, SndSettleMode}
3732+
]
3733+
|| Handle := #incoming_link{snd_settle_mode = SndSettleMode} <- Links].
37053734

37063735
unwrap_simple_type(V = {list, _}) ->
37073736
V;

deps/rabbitmq_management/priv/www/js/dispatcher.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ dispatcher_add(function(sammy) {
4848
var name = esc(this.params['name']);
4949
render({'connection': {path: '/connections/' + name,
5050
options: {ranges: ['data-rates-conn']}},
51-
'channels': '/connections/' + name + '/channels'},
51+
'channels': '/connections/' + name + '/channels',
52+
'sessions': '/connections/' + name + '/sessions'},
5253
'connection', '#/connections');
5354
});
5455
sammy.del('#/connections', function() {

deps/rabbitmq_management/priv/www/js/global.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ var ALL_COLUMNS =
107107
['rate-deliver', 'deliver / get', true],
108108
['rate-redeliver', 'redelivered', false],
109109
['rate-ack', 'ack', true]]},
110+
111+
'sessions' :
112+
{'Overview': [],
113+
'Session Flow Control': [['incoming-window', 'Incoming window', true]]},
114+
110115
'connections':
111116
{'Overview': [['container_id', 'Container ID', true],
112117
['user', 'User name', true],

deps/rabbitmq_management/priv/www/js/tmpl/connection.ejs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,23 @@
8484
</div>
8585
</div>
8686
87+
<% if (connection.protocol === "AMQP 1-0") { %>
88+
<div class="section">
89+
<h2 class="updatable" >Sessions (<%=(sessions.length)%>) </h2>
90+
<div class="hider updatable">
91+
<%= format('sessions-list', {'sessions': sessions}) %>
92+
</div>
93+
</div>
94+
<% } %>
95+
96+
<% if (connection.protocol === "AMQP 0-9-1") { %>
8797
<div class="section">
8898
<h2 class="updatable" >Channels (<%=(channels.length)%>) </h2>
8999
<div class="hider updatable">
90100
<%= format('channels-list', {'channels': channels, 'mode': 'connection'}) %>
91101
</div>
92102
</div>
103+
<% } %>
93104
94105
<% if (connection.ssl) { %>
95106
<div class="section">
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<table class="list">
2+
<thead>
3+
4+
<tr>
5+
<%= group_heading('sessions', 'Overview', [true]) %>
6+
<%= group_heading('sessions', 'Session Flow Control', []) %>
7+
<th class="plus-minus"><span class="popup-options-link" title="Click to change columns" type="columns" for="sessions">+/-</span></th>
8+
</tr>
9+
10+
<tr>
11+
<th>Channel number</th>
12+
<% if (show_column('sessions', 'incoming-window')) { %>
13+
<th>Incoming Window</th>
14+
<% } %>
15+
</tr>
16+
17+
</thead>
18+
19+
<tbody>
20+
<%
21+
for (var i = 0; i < sessions.length; i++) {
22+
var session = sessions[i];
23+
%>
24+
<tr>
25+
<td class="c"><%= fmt_string(session.channel_number) %></td>
26+
<% if (show_column('sessions', 'incoming-window')) { %>
27+
<td class="c"><%= fmt_string(session.incoming_window) %></td>
28+
<% } %>
29+
</tr>
30+
<% } %>
31+
</tbody>
32+
</table>

deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ dispatcher() ->
132132
{"/connections/:connection", rabbit_mgmt_wm_connection, []},
133133
{"/connections/username/:username", rabbit_mgmt_wm_connection_user_name, []},
134134
{"/connections/:connection/channels", rabbit_mgmt_wm_connection_channels, []},
135+
{"/connections/:connection/sessions", rabbit_mgmt_wm_connection_sessions, []},
135136
{"/channels", rabbit_mgmt_wm_channels, []},
136137
{"/channels/:channel", rabbit_mgmt_wm_channel, []},
137138
{"/consumers", rabbit_mgmt_wm_consumers, []},
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
%% This Source Code Form is subject to the terms of the Mozilla Public
2+
%% License, v. 2.0. If a copy of the MPL was not distributed with this
3+
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
%%
5+
%% Copyright (c) 2007-2024 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
6+
%%
7+
8+
-module(rabbit_mgmt_wm_connection_sessions).
9+
10+
-export([init/2, to_json/2, content_types_provided/2, is_authorized/2]).
11+
-export([resource_exists/2]).
12+
-export([variances/2]).
13+
14+
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
15+
-include_lib("rabbit_common/include/rabbit.hrl").
16+
17+
%%--------------------------------------------------------------------
18+
19+
init(Req, _State) ->
20+
{cowboy_rest, rabbit_mgmt_headers:set_common_permission_headers(Req, ?MODULE), #context{}}.
21+
22+
variances(Req, Context) ->
23+
{[<<"accept-encoding">>, <<"origin">>], Req, Context}.
24+
25+
content_types_provided(ReqData, Context) ->
26+
{rabbit_mgmt_util:responder_map(to_json), ReqData, Context}.
27+
28+
resource_exists(ReqData, Context) ->
29+
case conn(ReqData) of
30+
not_found ->
31+
{false, ReqData, Context};
32+
_Conn ->
33+
{true, ReqData, Context}
34+
end.
35+
36+
to_json(ReqData, Context) ->
37+
Conn = conn(ReqData),
38+
Protocol = proplists:get_value(protocol, Conn),
39+
case Protocol of
40+
{1, 0} ->
41+
ConnPid = proplists:get_value(pid, Conn),
42+
try rabbit_amqp_reader:info(ConnPid, [sessions]) of
43+
ConnInfos ->
44+
Sessions = proplists:get_value(sessions, ConnInfos),
45+
SessionPids = maps:values(Sessions),
46+
SessionInfos = session_infos(SessionPids),
47+
rabbit_mgmt_util:reply_list(
48+
SessionInfos, ["channel_number"], ReqData, Context)
49+
catch Type:Reason0 ->
50+
Reason = unicode:characters_to_binary(
51+
lists:flatten(
52+
io_lib:format(
53+
"failed to get sessions for connection ~p: ~s ~tp",
54+
[ConnPid, Type, Reason0]))),
55+
rabbit_mgmt_util:internal_server_error(Reason, ReqData, Context)
56+
end;
57+
_ ->
58+
rabbit_mgmt_util:reply([], ReqData, Context)
59+
end.
60+
61+
is_authorized(ReqData, Context) ->
62+
try
63+
rabbit_mgmt_util:is_authorized_user(ReqData, Context, conn(ReqData))
64+
catch
65+
{error, invalid_range_parameters, Reason} ->
66+
rabbit_mgmt_util:bad_request(iolist_to_binary(Reason), ReqData, Context)
67+
end.
68+
69+
%%--------------------------------------------------------------------
70+
71+
conn(Req) ->
72+
case rabbit_connection_tracking:lookup(rabbit_mgmt_util:id(connection, Req)) of
73+
#tracked_connection{name = Name,
74+
pid = Pid,
75+
protocol = Protocol,
76+
username = Username} ->
77+
[{name, Name},
78+
{pid, Pid},
79+
{protocol, Protocol},
80+
{user, Username}];
81+
not_found ->
82+
not_found
83+
end.
84+
85+
session_infos(SessionPids) ->
86+
lists:filtermap(
87+
fun(Pid) ->
88+
case rabbit_amqp_session:info(Pid) of
89+
{ok, Infos} ->
90+
{true, Infos};
91+
{error, Reason} ->
92+
rabbit_log:warning("failed to get infos for session ~p: ~tp",
93+
[Pid, Reason]),
94+
false
95+
end
96+
end, SessionPids).

0 commit comments

Comments
 (0)