From aef8b9a9f4fe5dc1caa2ee52ca5956dfd0ca3a88 Mon Sep 17 00:00:00 2001 From: Alexander Verbitsky Date: Tue, 17 Nov 2015 22:54:02 +0300 Subject: [PATCH] Rewriting of function for printing stacktrace in human readable form with using 'format_mfa' --- README.md | 7 ++-- src/error_logger_lager_h.erl | 2 +- src/lager.erl | 64 ++++++++---------------------------- test/pr_stacktrace_test.erl | 61 +++++++++++++++++++++++++--------- 4 files changed, 63 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index 1eb442b..eed11b5 100644 --- a/README.md +++ b/README.md @@ -399,9 +399,10 @@ Exception Pretty Printing try foo() catch - Class:Error -> - Stacktrace = lists:reverse(erlang:get_stacktrace()), - lager:error("~nStacktrace:~s~n~s:~p", [lager:pr_stacktrace(Stacktrace), Class, Error]) + Class:Reason -> + lager:error( + "~nStacktrace:~s", + [lager:pr_stacktrace(erlang:get_stacktrace(), {Class, Reason})]) end. ``` diff --git a/src/error_logger_lager_h.erl b/src/error_logger_lager_h.erl index 2bdab73..789ffab 100644 --- a/src/error_logger_lager_h.erl +++ b/src/error_logger_lager_h.erl @@ -31,7 +31,7 @@ -export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, code_change/3]). --export([format_reason/1]). +-export([format_reason/1, format_mfa/1, format_args/3]). -record(state, { shaper :: lager_shaper(), diff --git a/src/lager.erl b/src/lager.erl index a2d1625..9e4b051 100644 --- a/src/lager.erl +++ b/src/lager.erl @@ -33,7 +33,7 @@ get_loglevel/1, get_loglevel/2, set_loglevel/2, set_loglevel/3, set_loglevel/4, get_loglevels/1, update_loglevel_config/1, posix_error/1, set_loghwm/2, set_loghwm/3, set_loghwm/4, safe_format/3, safe_format_chop/3, unsafe_format/2, dispatch_log/5, dispatch_log/7, dispatch_log/9, - do_log/9, do_log/10, do_log_unsafe/10, pr/2, pr/3, pr_stacktrace/1]). + do_log/9, do_log/10, do_log_unsafe/10, pr/2, pr/3, pr_stacktrace/1, pr_stacktrace/2]). -type log_level() :: debug | info | notice | warning | error | critical | alert | emergency. -type log_level_number() :: 0..7. @@ -580,55 +580,17 @@ is_record_known(Record, Module) -> end end. -integer_to_binary(Integer) -> - case - erlang:is_builtin(erlang, integer_to_binary, 1) - of - true -> apply(erlang, integer_to_binary, 1); - % backward compatibility for old OTP versions - false -> list_to_binary(integer_to_list(Integer)) - end. %% @doc Print stacktrace in human readable form -pr_stacktrace([]) -> - <<"">>; -pr_stacktrace([Entry|Stacktrace]) -> - Indent = <<" ">>, - {Mod, Func, ArityOrArgs, Location} = Entry, - - BinMod = atom_to_binary(Mod, utf8), - BinFunc = atom_to_binary(Func, utf8), - - {Arity, Args} = case ArityOrArgs of - A when is_integer(A) -> {A, []}; - _ -> - {length(ArityOrArgs), ArityOrArgs} - end, - BinArity = integer_to_binary(Arity), - FunSpec = <<"fun ", BinMod/binary, ":", BinFunc/binary, "/", BinArity/binary>>, - - BinArgs = case Args of - [] -> <<"">>; - _ -> - BArgs = binary:replace( - list_to_binary(io_lib:format("~p", [Args])), - <<"\n">>, <<"">>, [global]), - <<"\n", Indent/binary, Indent/binary, "args ", BArgs/binary>> - end, - - BinLocation = case Location of - [{file, File}, {line, Line}] -> - BLine = integer_to_binary(Line), - BFile = list_to_binary(File), - << - "\n", Indent/binary, Indent/binary, "file \"", BFile/binary, "\"", - "\n", Indent/binary, Indent/binary, "line ", BLine/binary>>; - [] -> <<"">> - end, - - Output = << - "\n", Indent/binary, FunSpec/binary, - BinArgs/binary, - BinLocation/binary>>, - Rest = pr_stacktrace(Stacktrace), - <>. +pr_stacktrace(Stacktrace) -> + Indent = "\n ", + lists:foldl( + fun(Entry, Acc) -> + Acc ++ Indent ++ error_logger_lager_h:format_mfa(Entry) + end, + [], + lists:reverse(Stacktrace)). + +pr_stacktrace(Stacktrace, {Class, Reason}) -> + lists:flatten( + pr_stacktrace(Stacktrace) ++ "\n" ++ io_lib:format("~s:~p", [Class, Reason])). diff --git a/test/pr_stacktrace_test.erl b/test/pr_stacktrace_test.erl index dffa8bb..6e3d8cc 100644 --- a/test/pr_stacktrace_test.erl +++ b/test/pr_stacktrace_test.erl @@ -4,23 +4,52 @@ -include_lib("eunit/include/eunit.hrl"). -foo() -> - throw(test). +make_throw() -> + throw({test, exception}). -pr_stacktrace_test() -> +bad_arity() -> + lists:concat([], []). + +bad_arg() -> + integer_to_list(1.0). + +pr_stacktrace_throw_test() -> + Result = try + make_throw() + catch + Class:Reason -> + lager:pr_stacktrace(erlang:get_stacktrace(), {Class, Reason}) + end, +ExpectedPart = " + pr_stacktrace_test:pr_stacktrace_throw_test/0 line 18 + pr_stacktrace_test:make_throw/0 line 8 +throw:{test,exception}", + ?assertNotEqual(0, string:str(Result, ExpectedPart)). + + +pr_stacktrace_bad_arg_test() -> + Result = try + bad_arg() + catch + Class:Reason -> + lager:pr_stacktrace(erlang:get_stacktrace(), {Class, Reason}) + end, +ExpectedPart = " + pr_stacktrace_test:pr_stacktrace_bad_arg_test/0 line 32 + pr_stacktrace_test:bad_arg/0 line 14 +error:badarg", + ?assertNotEqual(0, string:str(Result, ExpectedPart)). + + +pr_stacktrace_bad_arity_test() -> Result = try - foo() + bad_arity() catch - _Class:_Error -> - Stacktrace = lists:reverse(erlang:get_stacktrace()), - lager:pr_stacktrace(Stacktrace) + Class:Reason -> + lager:pr_stacktrace(erlang:get_stacktrace(), {Class, Reason}) end, -ExpectedPart = <<" - fun pr_stacktrace_test:pr_stacktrace_test/0 - file \"test/pr_stacktrace_test.erl\" - line 12 - fun pr_stacktrace_test:foo/0 - file \"test/pr_stacktrace_test.erl\" - line 8">>, - - ?assertNotEqual(nomatch, binary:match(Result, ExpectedPart, [])). +ExpectedPart = " + pr_stacktrace_test:pr_stacktrace_bad_arity_test/0 line 46 + lists:concat([], []) +error:undef", + ?assertNotEqual(0, string:str(Result, ExpectedPart)). \ No newline at end of file