aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2015-08-21 10:54:00 +0200
committerBjörn Gustavsson <[email protected]>2015-09-07 10:35:32 +0200
commit3c3a5b08589a6e54b0d2d81e470fcffaaa74c15c (patch)
tree9eba1250c4895dfa761534d2285279139cf53c8d
parent62a8c96e22951d6b8d696b32d898c823969f4812 (diff)
downloadotp-3c3a5b08589a6e54b0d2d81e470fcffaaa74c15c.tar.gz
otp-3c3a5b08589a6e54b0d2d81e470fcffaaa74c15c.tar.bz2
otp-3c3a5b08589a6e54b0d2d81e470fcffaaa74c15c.zip
Teach error_logger_tty_h to truncate big messages
Add the possibility to truncate big messages to avoid running out of memory.
-rw-r--r--lib/stdlib/src/error_logger_tty_h.erl44
-rw-r--r--lib/stdlib/test/error_logger_h_SUITE.erl41
2 files changed, 70 insertions, 15 deletions
diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl
index 5dd8b0caa0..d2df6681e3 100644
--- a/lib/stdlib/src/error_logger_tty_h.erl
+++ b/lib/stdlib/src/error_logger_tty_h.erl
@@ -33,17 +33,19 @@
handle_event/2, handle_call/2, handle_info/2,
terminate/2, code_change/3]).
--export([write_event/2]).
+-export([write_event/2,write_event/3]).
-record(st,
{user,
prev_handler,
- io_mod=io}).
+ io_mod=io,
+ depth=unlimited}).
%% This one is used when we takeover from the simple error_logger.
init({[], {error_logger, Buf}}) ->
User = set_group_leader(),
- State = #st{user=User,prev_handler=error_logger},
+ Depth = get_depth(),
+ State = #st{user=User,prev_handler=error_logger,depth=Depth},
write_events(State, Buf),
{ok, State};
%% This one is used if someone took over from us, and now wants to
@@ -54,7 +56,16 @@ init({[], {error_logger_tty_h, PrevHandler}}) ->
%% This one is used when we are started directly.
init([]) ->
User = set_group_leader(),
- {ok, #st{user=User,prev_handler=[]}}.
+ Depth = get_depth(),
+ {ok, #st{user=User,prev_handler=[],depth=Depth}}.
+
+get_depth() ->
+ case application:get_env(kernel, error_logger_format_depth) of
+ {ok, Depth} when is_integer(Depth) ->
+ max(10, Depth);
+ undefined ->
+ unlimited
+ end.
handle_event({_Type, GL, _Msg}, State) when node(GL) =/= node() ->
{ok, State};
@@ -88,6 +99,9 @@ code_change(_OldVsn, State, _Extra) ->
write_event(Event, IoMod) ->
do_write_event(#st{io_mod=IoMod}, Event).
+write_event(Event, IoMod, Depth) ->
+ do_write_event(#st{io_mod=IoMod,depth=Depth}, Event).
+
%%% ------------------------------------------------------
%%% Misc. functions.
@@ -140,17 +154,35 @@ do_write_event(_, _) ->
ok.
format_body(State, [{Format,Args}|T]) ->
- S = try io_lib:format(Format, Args) of
+ S = try format(State, Format, Args) of
S0 ->
S0
catch
_:_ ->
- io_lib:format("ERROR: ~p - ~p\n", [Format,Args])
+ format(State, "ERROR: ~p - ~p\n", [Format,Args])
end,
[S|format_body(State, T)];
format_body(_State, []) ->
[].
+format(#st{depth=unlimited}, Format, Args) ->
+ io_lib:format(Format, Args);
+format(#st{depth=Depth}, Format0, Args) ->
+ Format1 = io_lib:scan_format(Format0, Args),
+ Format = limit_format(Format1, Depth),
+ io_lib:build_text(Format).
+
+limit_format([#{control_char:=C0}=M0|T], Depth) when C0 =:= $p;
+ C0 =:= $w ->
+ C = C0 - ($a - $A), %To uppercase.
+ #{args:=Args} = M0,
+ M = M0#{control_char:=C,args:=Args++[Depth]},
+ [M|limit_format(T, Depth)];
+limit_format([H|T], Depth) ->
+ [H|limit_format(T, Depth)];
+limit_format([], _) ->
+ [].
+
parse_event({error, _GL, {Pid, Format, Args}}) ->
{"ERROR REPORT",Pid,[{Format,Args}]};
parse_event({info_msg, _GL, {Pid, Format, Args}}) ->
diff --git a/lib/stdlib/test/error_logger_h_SUITE.erl b/lib/stdlib/test/error_logger_h_SUITE.erl
index 7cde659b9f..b0b9c717a1 100644
--- a/lib/stdlib/test/error_logger_h_SUITE.erl
+++ b/lib/stdlib/test/error_logger_h_SUITE.erl
@@ -20,7 +20,7 @@
-module(error_logger_h_SUITE).
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
--export([logfile/1,logfile_truncated/1,tty/1]).
+-export([logfile/1,logfile_truncated/1,tty/1,tty_truncated/1]).
%% Event handler exports.
-export([init/1,handle_event/2,terminate/2]).
@@ -30,7 +30,7 @@
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [logfile,logfile_truncated,tty].
+ [logfile,logfile_truncated,tty,tty_truncated].
groups() ->
[].
@@ -118,6 +118,25 @@ tty(Config) ->
cleanup(Log),
ok.
+tty_truncated(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ LogDir = filename:join(PrivDir, ?MODULE),
+ Log = filename:join(LogDir, "tty_truncated.log"),
+ ok = filelib:ensure_dir(Log),
+
+ Ev = event_templates(),
+
+ Depth = 20,
+ application:set_env(kernel, error_logger_format_depth, Depth),
+ try
+ do_one_tty(Log, Ev, Depth)
+ after
+ application:unset_env(kernel, error_logger_format_depth)
+ end,
+
+ cleanup(Log),
+ ok.
+
do_one_tty(Log, Ev, Depth) ->
tty_log_open(Log),
gen_events(Ev),
@@ -126,7 +145,11 @@ do_one_tty(Log, Ev, Depth) ->
tty_log_open(Log) ->
{ok,Fd} = file:open(Log, [write]),
- error_logger:add_report_handler(?MODULE, Fd),
+ Depth = case application:get_env(kernel, error_logger_format_depth) of
+ {ok,D} -> D;
+ _ -> unlimited
+ end,
+ error_logger:add_report_handler(?MODULE, {Fd,Depth}),
Fd.
tty_log_close() ->
@@ -357,19 +380,19 @@ dl_format_1([], [], _, Facc, Aacc) ->
%%% calling error_logger_tty_h:write_event/2.
%%%
-init(Fd) ->
- {ok,Fd}.
+init({_,_}=St) ->
+ {ok,St}.
-handle_event(Event, Fd) ->
- case error_logger_tty_h:write_event(tag_event(Event), io_lib) of
+handle_event(Event, {Fd,Depth}=St) ->
+ case error_logger_tty_h:write_event(tag_event(Event), io_lib, Depth) of
ok ->
ok;
Str when is_list(Str) ->
io:put_chars(Fd, Str)
end,
- {ok,Fd}.
+ {ok,St}.
-terminate(_Reason, Fd) ->
+terminate(_Reason, {Fd,_}) ->
ok = file:close(Fd),
[].