Skip to content

Commit b9eebc4

Browse files
Merge pull request #12215 from rabbitmq/add-connection-duration-to-closing-message
Add connection duration to "closing AMQP connection..." msgs
2 parents c0a1c0c + a866ad3 commit b9eebc4

File tree

1 file changed

+84
-47
lines changed

1 file changed

+84
-47
lines changed

deps/rabbit/src/rabbit_reader.erl

Lines changed: 84 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ start_connection(Parent, HelperSups, RanchRef, Deb, Sock) ->
318318
{PeerHost, PeerPort, Host, Port} =
319319
socket_op(Sock, fun (S) -> rabbit_net:socket_ends(S, inbound) end),
320320
?store_proc_name(Name),
321+
ConnectedAt = os:system_time(milli_seconds),
321322
State = #v1{parent = Parent,
322323
ranch_ref = RanchRef,
323324
sock = RealSocket,
@@ -337,8 +338,7 @@ start_connection(Parent, HelperSups, RanchRef, Deb, Sock) ->
337338
capabilities = [],
338339
auth_mechanism = none,
339340
auth_state = none,
340-
connected_at = os:system_time(
341-
milli_seconds)},
341+
connected_at = ConnectedAt},
342342
callback = uninitialized_callback,
343343
recv_len = 0,
344344
pending_recv = false,
@@ -362,17 +362,23 @@ start_connection(Parent, HelperSups, RanchRef, Deb, Sock) ->
362362
handshake, 8)]}) of
363363
%% connection was closed cleanly by the client
364364
#v1{connection = #connection{user = #user{username = Username},
365-
vhost = VHost}} ->
366-
rabbit_log_connection:info("closing AMQP connection (~ts, vhost: '~ts', user: '~ts')",
367-
[dynamic_connection_name(Name), VHost, Username]);
365+
vhost = VHost,
366+
connected_at = ConnectedAt0}} ->
367+
ConnName = dynamic_connection_name(Name),
368+
ConnDuration = connection_duration(ConnectedAt0),
369+
rabbit_log_connection:info("closing AMQP connection (~ts, vhost: '~ts', user: '~ts', duration: '~ts')",
370+
[ConnName, VHost, Username, ConnDuration]);
368371
%% just to be more defensive
369372
_ ->
370-
rabbit_log_connection:info("closing AMQP connection (~ts)",
371-
[dynamic_connection_name(Name)])
372-
end
373+
ConnName = dynamic_connection_name(Name),
374+
ConnDuration = connection_duration(ConnectedAt),
375+
rabbit_log_connection:info("closing AMQP connection (~ts, duration: '~ts')",
376+
[ConnName, ConnDuration])
377+
end
373378
catch
374379
Ex ->
375-
log_connection_exception(dynamic_connection_name(Name), Ex)
380+
ConnNameEx = dynamic_connection_name(Name),
381+
log_connection_exception(ConnNameEx, ConnectedAt, Ex)
376382
after
377383
%% We don't call gen_tcp:close/1 here since it waits for
378384
%% pending output to be sent, which results in unnecessary
@@ -400,56 +406,67 @@ start_connection(Parent, HelperSups, RanchRef, Deb, Sock) ->
400406
end,
401407
done.
402408

403-
log_connection_exception(Name, Ex) ->
409+
log_connection_exception(Name, ConnectedAt, Ex) ->
404410
Severity = case Ex of
405411
connection_closed_with_no_data_received -> debug;
406412
{connection_closed_abruptly, _} -> warning;
407413
connection_closed_abruptly -> warning;
408414
_ -> error
409415
end,
410-
log_connection_exception(Severity, Name, Ex).
416+
log_connection_exception(Severity, Name, ConnectedAt, Ex).
411417

412-
log_connection_exception(Severity, Name, {heartbeat_timeout, TimeoutSec}) ->
418+
log_connection_exception(Severity, Name, ConnectedAt, {heartbeat_timeout, TimeoutSec}) ->
419+
ConnDuration = connection_duration(ConnectedAt),
420+
Fmt = "closing AMQP connection ~tp (~ts, duration: '~ts'):~n"
421+
"missed heartbeats from client, timeout: ~ps",
413422
%% Long line to avoid extra spaces and line breaks in log
414-
log_connection_exception_with_severity(Severity,
415-
"closing AMQP connection ~tp (~ts):~n"
416-
"missed heartbeats from client, timeout: ~ps",
417-
[self(), Name, TimeoutSec]);
418-
log_connection_exception(Severity, Name, {connection_closed_abruptly,
419-
#v1{connection = #connection{user = #user{username = Username},
420-
vhost = VHost}}}) ->
421-
log_connection_exception_with_severity(Severity,
422-
"closing AMQP connection ~tp (~ts, vhost: '~ts', user: '~ts'):~nclient unexpectedly closed TCP connection",
423-
[self(), Name, VHost, Username]);
423+
log_connection_exception_with_severity(Severity, Fmt,
424+
[self(), Name, ConnDuration, TimeoutSec]);
425+
log_connection_exception(Severity, Name, _ConnectedAt,
426+
{connection_closed_abruptly,
427+
#v1{connection = #connection{user = #user{username = Username},
428+
vhost = VHost,
429+
connected_at = ConnectedAt}}}) ->
430+
ConnDuration = connection_duration(ConnectedAt),
431+
Fmt = "closing AMQP connection ~tp (~ts, vhost: '~ts', user: '~ts', duration: '~ts'):~n"
432+
"client unexpectedly closed TCP connection",
433+
log_connection_exception_with_severity(Severity, Fmt,
434+
[self(), Name, VHost, Username, ConnDuration]);
424435
%% when client abruptly closes connection before connection.open/authentication/authorization
425436
%% succeeded, don't log username and vhost as 'none'
426-
log_connection_exception(Severity, Name, {connection_closed_abruptly, _}) ->
427-
log_connection_exception_with_severity(Severity,
428-
"closing AMQP connection ~tp (~ts):~nclient unexpectedly closed TCP connection",
429-
[self(), Name]);
437+
log_connection_exception(Severity, Name, ConnectedAt, {connection_closed_abruptly, _}) ->
438+
ConnDuration = connection_duration(ConnectedAt),
439+
Fmt = "closing AMQP connection ~tp (~ts, duration: '~ts'):~n"
440+
"client unexpectedly closed TCP connection",
441+
log_connection_exception_with_severity(Severity, Fmt,
442+
[self(), Name, ConnDuration]);
430443
%% failed connection.tune negotiations
431-
log_connection_exception(Severity, Name, {handshake_error, tuning, _Channel,
432-
{exit, #amqp_error{explanation = Explanation},
433-
_Method, _Stacktrace}}) ->
434-
log_connection_exception_with_severity(Severity,
435-
"closing AMQP connection ~tp (~ts):~nfailed to negotiate connection parameters: ~ts",
436-
[self(), Name, Explanation]);
437-
log_connection_exception(Severity, Name, {sasl_required, ProtocolId}) ->
438-
log_connection_exception_with_severity(
439-
Severity,
440-
"closing AMQP 1.0 connection (~ts): RabbitMQ requires SASL "
441-
"security layer (expected protocol ID 3, but client sent protocol ID ~b)",
442-
[Name, ProtocolId]);
444+
log_connection_exception(Severity, Name, ConnectedAt, {handshake_error, tuning, _Channel,
445+
{exit, #amqp_error{explanation = Explanation},
446+
_Method, _Stacktrace}}) ->
447+
ConnDuration = connection_duration(ConnectedAt),
448+
Fmt = "closing AMQP connection ~tp (~ts):~n"
449+
"failed to negotiate connection parameters: ~ts",
450+
log_connection_exception_with_severity(Severity, Fmt, [self(), Name, ConnDuration, Explanation]);
451+
log_connection_exception(Severity, Name, ConnectedAt, {sasl_required, ProtocolId}) ->
452+
ConnDuration = connection_duration(ConnectedAt),
453+
Fmt = "closing AMQP 1.0 connection (~ts, duration: '~ts'): RabbitMQ requires SASL "
454+
"security layer (expected protocol ID 3, but client sent protocol ID ~b)",
455+
log_connection_exception_with_severity(Severity, Fmt,
456+
[Name, ConnDuration, ProtocolId]);
443457
%% old exception structure
444-
log_connection_exception(Severity, Name, connection_closed_abruptly) ->
445-
log_connection_exception_with_severity(Severity,
446-
"closing AMQP connection ~tp (~ts):~n"
447-
"client unexpectedly closed TCP connection",
448-
[self(), Name]);
449-
log_connection_exception(Severity, Name, Ex) ->
450-
log_connection_exception_with_severity(Severity,
451-
"closing AMQP connection ~tp (~ts):~n~tp",
452-
[self(), Name, Ex]).
458+
log_connection_exception(Severity, Name, ConnectedAt, connection_closed_abruptly) ->
459+
ConnDuration = connection_duration(ConnectedAt),
460+
Fmt = "closing AMQP connection ~tp (~ts, duration: '~ts'):~n"
461+
"client unexpectedly closed TCP connection",
462+
log_connection_exception_with_severity(Severity, Fmt,
463+
[self(), Name, ConnDuration]);
464+
log_connection_exception(Severity, Name, ConnectedAt, Ex) ->
465+
ConnDuration = connection_duration(ConnectedAt),
466+
Fmt = "closing AMQP connection ~tp (~ts, duration: '~ts'):~n"
467+
"~tp",
468+
log_connection_exception_with_severity(Severity, Fmt,
469+
[self(), Name, ConnDuration, Ex]).
453470

454471
log_connection_exception_with_severity(Severity, Fmt, Args) ->
455472
case Severity of
@@ -1828,3 +1845,23 @@ get_client_value_detail(channel_max, 0) ->
18281845
" (no limit)";
18291846
get_client_value_detail(_Field, _ClientValue) ->
18301847
"".
1848+
1849+
connection_duration(ConnectedAt) ->
1850+
Now = os:system_time(milli_seconds),
1851+
DurationMillis = Now - ConnectedAt,
1852+
if
1853+
DurationMillis >= 1000 ->
1854+
DurationSecs = DurationMillis div 1000,
1855+
case calendar:seconds_to_daystime(DurationSecs) of
1856+
{0, {0, 0, Seconds}} ->
1857+
io_lib:format("~Bs", [Seconds]);
1858+
{0, {0, Minutes, Seconds}} ->
1859+
io_lib:format("~BM, ~Bs", [Minutes, Seconds]);
1860+
{0, {Hours, Minutes, Seconds}} ->
1861+
io_lib:format("~BH, ~BM, ~Bs", [Hours, Minutes, Seconds]);
1862+
{Days, {Hours, Minutes, Seconds}} ->
1863+
io_lib:format("~BD, ~BH, ~BM, ~Bs", [Days, Hours, Minutes, Seconds])
1864+
end;
1865+
true ->
1866+
io_lib:format("~Bms", [DurationMillis])
1867+
end.

0 commit comments

Comments
 (0)