diff --git a/src/error_logger_lager_h.erl b/src/error_logger_lager_h.erl index 3bbe468..cfe2667 100644 --- a/src/error_logger_lager_h.erl +++ b/src/error_logger_lager_h.erl @@ -188,8 +188,16 @@ format_offender(Off) -> format_reason({'function not exported', [{M, F, A},MFA|_]}) -> ["call to undefined function ", format_mfa({M, F, length(A)}), " from ", format_mfa(MFA)]; +format_reason({'function not exported', [{M, F, A, _Props},MFA|_]}) -> + %% R15 line numbers + ["call to undefined function ", format_mfa({M, F, length(A)}), + " from ", format_mfa(MFA)]; format_reason({undef, [MFA|_]}) -> ["call to undefined function ", format_mfa(MFA)]; +format_reason({bad_return, {_MFA, {'EXIT', Reason}}}) -> + format_reason(Reason); +format_reason({bad_return, {MFA, Val}}) -> + ["bad return value ", print_val(Val), " from ", format_mfa(MFA)]; format_reason({bad_return_value, Val}) -> ["bad return value: ", print_val(Val)]; format_reason({{bad_return_value, Val}, MFA}) -> @@ -227,6 +235,9 @@ format_reason({system_limit, [{M, F, _}|_] = Trace}) -> ["system limit: ", Limit]; format_reason({badarg, [MFA,MFA2|_]}) -> case MFA of + {_M, _F, A, _Props} when is_list(A) -> + %% R15 line numbers + ["bad argument in call to ", format_mfa(MFA), " in ", format_mfa(MFA2)]; {_M, _F, A} when is_list(A) -> ["bad argument in call to ", format_mfa(MFA), " in ", format_mfa(MFA2)]; _ -> @@ -250,6 +261,13 @@ format_mfa({M, F, A}) when is_list(A) -> io_lib:format("~w:~w("++FmtStr++")", [M, F | Args]); format_mfa({M, F, A}) when is_integer(A) -> io_lib:format("~w:~w/~w", [M, F, A]); +format_mfa({M, F, A, Props}) when is_list(Props) -> + case proplists:get_value(line, Props) of + undefined -> + format_mfa({M, F, A}); + Line -> + [format_mfa({M, F, A}), io_lib:format(" line ~w", [Line])] + end; format_mfa(Other) -> io_lib:format("~w", [Other]). diff --git a/test/lager_test_backend.erl b/test/lager_test_backend.erl index b6bc71c..b25e03f 100644 --- a/test/lager_test_backend.erl +++ b/test/lager_test_backend.erl @@ -87,6 +87,12 @@ count_ignored() -> flush() -> gen_event:call(lager_event, ?MODULE, flush). +has_line_numbers() -> + %% are we R15 or greater + Rel = erlang:system_info(otp_release), + {match, [Major]} = re:run(Rel, "^R(\\d+)[A|B](|0(\\d))$", [{capture, [1], list}]), + list_to_integer(Major) >= 15. + not_running_test() -> ?assertEqual({error, lager_not_running}, lager:log(info, self(), "not running")). @@ -241,6 +247,18 @@ crash(Type) -> _ = gen_event:which_handlers(error_logger), ok. +test_body(Expected, Actual) -> + case has_line_numbers() of + true -> + FileLine = string:substr(Actual, length(Expected)+1), + Body = string:substr(Actual, 1, length(Expected)), + ?assertEqual(Expected, Body), + ?assertEqual(" line ", string:substr(FileLine, 1, 6)); + false -> + ?assertEqual(Expected, Actual) + end. + + error_logger_redirect_crash_test_() -> {foreach, fun() -> @@ -293,7 +311,7 @@ error_logger_redirect_crash_test_() -> crash(case_clause), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no case clause matching {} in crash:handle_call/3", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"case clause string", @@ -302,7 +320,7 @@ error_logger_redirect_crash_test_() -> crash(case_clause_string), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no case clause matching \"crash\" in crash:handle_call/3", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"function clause", @@ -311,7 +329,7 @@ error_logger_redirect_crash_test_() -> crash(function_clause), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no function clause matching crash:function({})", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"if clause", @@ -320,7 +338,7 @@ error_logger_redirect_crash_test_() -> crash(if_clause), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no true branch found while evaluating if expression in crash:handle_call/3", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"try clause", @@ -329,7 +347,7 @@ error_logger_redirect_crash_test_() -> crash(try_clause), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no try clause matching [] in crash:handle_call/3", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"undefined function", @@ -338,7 +356,7 @@ error_logger_redirect_crash_test_() -> crash(undef), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: call to undefined function crash:booger/0 from crash:handle_call/3", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"bad math", @@ -347,7 +365,7 @@ error_logger_redirect_crash_test_() -> crash(badarith), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad arithmetic expression in crash:handle_call/3", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"bad match", @@ -356,7 +374,7 @@ error_logger_redirect_crash_test_() -> crash(badmatch), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: no match of right hand value {} in crash:handle_call/3", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"bad arity", @@ -365,7 +383,7 @@ error_logger_redirect_crash_test_() -> crash(badarity), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: fun called with wrong arity of 1 instead of 3 in crash:handle_call/3", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"bad arg1", @@ -374,7 +392,7 @@ error_logger_redirect_crash_test_() -> crash(badarg1), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad argument in crash:handle_call/3", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"bad arg2", @@ -383,7 +401,7 @@ error_logger_redirect_crash_test_() -> crash(badarg2), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad argument in call to erlang:iolist_to_binary([\"foo\",bar]) in crash:handle_call/3", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"noproc", @@ -401,7 +419,7 @@ error_logger_redirect_crash_test_() -> crash(badfun), {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~w gen_server crash terminated with reason: bad function booger in crash:handle_call/3", [Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end } @@ -699,7 +717,7 @@ error_logger_redirect_test_() -> {_, _, Msg} = pop(), Expected = lists:flatten(io_lib:format("[error] ~p CRASH REPORT Process ~p with 0 neighbours crashed with reason: no function clause matching special_process:foo(bar)", [Pid, Pid])), - ?assertEqual(Expected, lists:flatten(Msg)) + test_body(Expected, lists:flatten(Msg)) end }, {"messages should not be generated if they don't satisfy the threshold",