diff options
author | Björn Gustavsson <[email protected]> | 2015-08-21 10:54:00 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2015-09-07 10:35:32 +0200 |
commit | 3c3a5b08589a6e54b0d2d81e470fcffaaa74c15c (patch) | |
tree | 9eba1250c4895dfa761534d2285279139cf53c8d | |
parent | 62a8c96e22951d6b8d696b32d898c823969f4812 (diff) | |
download | otp-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.erl | 44 | ||||
-rw-r--r-- | lib/stdlib/test/error_logger_h_SUITE.erl | 41 |
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), []. |