summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Watson <tim@rabbitmq.com>2014-03-20 14:04:32 +0000
committerTim Watson <tim@rabbitmq.com>2014-03-20 14:04:32 +0000
commit53e244503f748b76c94142d879e9d51470f37a04 (patch)
tree108d3a103710b9e83ad3a46c0e52b7ae98d4f96a
parent357fcc0b63d32f563736afffc142781631ba49dc (diff)
downloadrabbitmq-server-53e244503f748b76c94142d879e9d51470f37a04.tar.gz
Initial stab at limiting term size during logging
-rw-r--r--src/rabbit_error_logger.erl5
-rw-r--r--src/rabbit_sasl_report_file_h.erl9
-rw-r--r--src/rabbit_trunc_term.erl76
3 files changed, 86 insertions, 4 deletions
diff --git a/src/rabbit_error_logger.erl b/src/rabbit_error_logger.erl
index 313cc865..e921925e 100644
--- a/src/rabbit_error_logger.erl
+++ b/src/rabbit_error_logger.erl
@@ -87,9 +87,12 @@ publish1(RoutingKey, Format, Data, LogExch) ->
%% 0-9-1 says the timestamp is a "64 bit POSIX timestamp". That's
%% second resolution, not millisecond.
Timestamp = rabbit_misc:now_ms() div 1000,
+
+ %% TODO: is 'Data' ever in crash report format? I think not, but check...
+ Args = [rabbit_trunc_term:truncate_log_event(A) || A <- Data],
{ok, _DeliveredQPids} =
rabbit_basic:publish(LogExch, RoutingKey,
#'P_basic'{content_type = <<"text/plain">>,
timestamp = Timestamp},
- list_to_binary(io_lib:format(Format, Data))),
+ list_to_binary(io_lib:format(Format, Args))),
ok.
diff --git a/src/rabbit_sasl_report_file_h.erl b/src/rabbit_sasl_report_file_h.erl
index 823816c0..1b950c23 100644
--- a/src/rabbit_sasl_report_file_h.erl
+++ b/src/rabbit_sasl_report_file_h.erl
@@ -66,13 +66,16 @@ init_file({File, Type}) ->
end.
handle_event(Event, State) ->
- sasl_report_file_h:handle_event(Event, State).
+ Event2 = rabbit_trunc_term:truncate_log_event(Event),
+ sasl_report_file_h:handle_event(Event2, State).
handle_info(Event, State) ->
- sasl_report_file_h:handle_info(Event, State).
+ Event2 = rabbit_trunc_term:truncate_log_event(Event),
+ sasl_report_file_h:handle_info(Event2, State).
handle_call(Event, State) ->
- sasl_report_file_h:handle_call(Event, State).
+ Event2 = rabbit_trunc_term:truncate_log_event(Event),
+ sasl_report_file_h:handle_call(Event2, State).
terminate(Reason, State) ->
sasl_report_file_h:terminate(Reason, State).
diff --git a/src/rabbit_trunc_term.erl b/src/rabbit_trunc_term.erl
new file mode 100644
index 00000000..f519aad5
--- /dev/null
+++ b/src/rabbit_trunc_term.erl
@@ -0,0 +1,76 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License
+%% at http://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and
+%% limitations under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developer of the Original Code is GoPivotal, Inc.
+%% Copyright (c) 2007-2014 GoPivotal, Inc. All rights reserved.
+%%
+
+-module(rabbit_trunc_term).
+
+-export([truncate_log_event/1, shrink_term/1]).
+
+truncate_log_event({Type, GL, {Pid, Format, Args}})
+ when Type =:= error orelse
+ Type =:= info_msg orelse
+ Type =:= warning_msg ->
+ {Type, GL, {Pid, Format, [shrink_term(T) || T <- Args]}};
+truncate_log_event({Type, GL, {Pid, ReportType, Report}})
+ when Type =:= error_report orelse
+ Type =:= info_report orelse
+ Type =:= warning_report ->
+ Report2 = case ReportType of
+ crash_report -> [[{K, shrink_term(V)} || {K, V} <- R] ||
+ R <- Report];
+ _ -> [{K, shrink_term(V)} || {K, V} <- Report]
+ end,
+ {Type, GL, {Pid, ReportType, Report2}};
+truncate_log_event(Event) ->
+ Event.
+
+shrink_term(T) -> shrink_term(T, 10).
+
+%% TODO: avoid copying
+%% TODO: can we get away with using binary:part/3 (OTP vsn requirements)?
+%% TODO: reconsider depth limit handling
+shrink_term(T, 0) -> T;
+shrink_term(T, N) when is_binary(T) andalso size(T) > N ->
+ case size(T) - N of
+ Sz when Sz >= 1 -> Head = binary:part(T, 0, N-3),
+ <<Head/binary, <<"...">>/binary>>;
+ _ -> T
+ end;
+shrink_term([A|B], N) when not is_list(B) ->
+ shrink_term([A,B], N);
+shrink_term(T, N) when is_list(T) ->
+ IsPrintable = io_lib:printable_list(T),
+ case length(T) > N of
+ true when IsPrintable ->
+ lists:append(lists:sublist(T, N-3), "...");
+ true ->
+ lists:append([shrink_term(E, N-1) || E <- lists:sublist(T, N-1)],
+ ['...']);
+ false when IsPrintable ->
+ T;
+ false ->
+ [shrink_term(E, N-1) || E <- T]
+ end;
+shrink_term(T, N) when is_tuple(T) ->
+ case tuple_size(T) > N of
+ true -> list_to_tuple(
+ lists:append([shrink_term(E, N-1) ||
+ E <- lists:sublist(tuple_to_list(T), N-1)],
+ ['...']));
+ false -> list_to_tuple([shrink_term(E, N-1) ||
+ E <- tuple_to_list(T)])
+ end;
+shrink_term(T, _) -> T.
+