Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

A bunch more work on the error_logger interop

  • Loading branch information...
commit b7a56487e5efee2ee90b5d4a7ccd2a911772ff90 1 parent 04792f1
@Vagabond Vagabond authored
Showing with 92 additions and 34 deletions.
  1. +67 −21 src/error_logger_lager_h.erl
  2. +25 −13 src/lager.erl
View
88 src/error_logger_lager_h.erl
@@ -30,24 +30,44 @@ handle_call(_Request, State) ->
handle_event(Event, State) ->
case Event of
{error, _GL, {Pid, Fmt, Args}} ->
- lager:log(error, Pid, Fmt, Args);
- {info_msg, _GL, {Pid, Fmt, Args}} ->
- lager:log(info, Pid, Fmt, Args);
+ case Fmt of
+ "** Generic server "++_ ->
+ %% gen_server terminate
+ [Name, _Msg, _State, Reason] = Args,
+ lager:log(error, Pid, "gen_server ~w crashed with reason: ~s",
+ [Name, format_reason(Reason)]);
+ "** State machine "++_ ->
+ %% gen_fsm terminate
+ [Name, _Msg, StateName, _StateData, Reason] = Args,
+ lager:log(error, Pid, "gen_fsm ~w in state ~w crashed with reason: ~s",
+ [Name, StateName, format_reason(Reason)]);
+ "** gen_event handler"++_ ->
+ %% gen_event handler terminate
+ [ID, Name, _Msg, _State, Reason] = Args,
+ lager:log(error, Pid, "gen_event ~w installed in ~w crashed with reason: ~s",
+ [ID, Name, format_reason(Reason)]);
+ _ ->
+ lager:log(error, Pid, Fmt, Args)
+ end;
{error_report, _GL, {Pid, std_error, D}} ->
lager:log(error, Pid, print_silly_list(D));
{error_report, _GL, {Pid, supervisor_report, D}} ->
case lists:sort(D) of
[{errorContext, Ctx}, {offender, Off}, {reason, Reason}, {supervisor, Name}] ->
Offender = format_offender(Off),
- lager:log(error, Pid, "Supervisor ~p had child ~s exit with reason ~p in context ~p", [element(2, Name), Offender, Reason, Ctx]);
+ lager:log(error, Pid, "Supervisor ~w had child ~s exit with reason ~w in context ~w", [element(2, Name), Offender, Reason, Ctx]);
_ ->
lager:log(error, Pid, "SUPERVISOR REPORT" ++ print_silly_list(D))
end;
+ {error_report, _GL, {Pid, crash_report, [Self, Neighbours]}} ->
+ lager:log(error, Pid, "CRASH REPORT " ++ format_crash_report(Self));
+ {info_msg, _GL, {Pid, Fmt, Args}} ->
+ lager:log(info, Pid, Fmt, Args);
{info_report, _GL, {Pid, std_info, D}} ->
Details = lists:sort(D),
case Details of
[{application, App}, {exited, Reason}, {type, _Type}] ->
- lager:log(info, Pid, "Application ~p exited with reason: ~p", [App, Reason]);
+ lager:log(info, Pid, "Application ~w exited with reason: ~w", [App, Reason]);
_ ->
lager:log(info, Pid, print_silly_list(D))
end;
@@ -55,17 +75,17 @@ handle_event(Event, State) ->
Details = lists:sort(D),
case Details of
[{application, App}, {started_at, Node}] ->
- lager:log(info, P, "Application ~p started on node ~p",
+ lager:log(info, P, "Application ~w started on node ~w",
[App, Node]);
[{started, Started}, {supervisor, Name}] ->
MFA = format_mfa(proplists:get_value(mfargs, Started)),
Pid = proplists:get_value(pid, Started),
- lager:log(info, P, "Supervisor ~p started ~s at pid ~p", [element(2, Name), MFA, Pid]);
+ lager:log(info, P, "Supervisor ~w started ~s at pid ~w", [element(2, Name), MFA, Pid]);
_ ->
lager:log(info, P, "PROGRESS REPORT" ++ print_silly_list(D))
end;
_ ->
- io:format("Event ~p~n", [Event])
+ io:format("Event ~w~n", [Event])
end,
{ok, State}.
@@ -80,32 +100,58 @@ code_change(_OldVsn, State, _Extra) ->
%% internal functions
-print_silly_list(L) ->
- case lager_stdlib:string_p(L) of
- true -> L;
- _ -> print_silly_list(L, [], [])
- end.
+format_crash_report(Report) ->
+ Name = proplists:get_value(registered_name, Report, proplists:get_value(pid, Report)),
+ {_Class, Reason, _Trace} = proplists:get_value(error_info, Report),
+ %Arity = case A of
+ %A when is_integer(A) -> A;
+ %A when is_list(A) -> length(A)
+ %end,
+ io_lib:format("Process ~w crashed with reason: ~s", [Name, format_reason(Reason)]).
format_offender(Off) ->
case proplists:get_value(name, Off) of
undefined ->
%% supervisor_bridge
- io_lib:format("at module ~p at ~p", [proplists:get_value(mod, Off), proplists:get_value(pid, Off)]);
+ io_lib:format("at module ~w at ~w", [proplists:get_value(mod, Off), proplists:get_value(pid, Off)]);
Name ->
%% regular supervisor
MFA = format_mfa(proplists:get_value(mfargs, Off)),
- io_lib:format("with name ~p started with ~s at ~p", [Name, MFA, proplists:get_value(pid, Off)])
+ io_lib:format("with name ~w started with ~s at ~w", [Name, MFA, proplists:get_value(pid, Off)])
end.
-format_mfa({M, F, A}) ->
- %% TODO pretty-print args better
- io_lib:format("~p:~p(~p)", [M, F, A]);
+format_reason({undef, [{M, F, A}|_]}) ->
+ io_lib:format("call to undefined function ~w:~w/~w", [M, F, length(A)]);
+format_reason({bad_return_value, Val}) ->
+ io_lib:format("bad return value: ~w", [Val]);
+format_reason({{case_clause, Val}, [{M, F, A}|_]}) ->
+ io_lib:format("no case clause matching ~w in ~w:~w/~w", [Val, M, F, A]);
+format_reason({function_clause, [MFA|_]}) ->
+ "no function clause matching " ++ format_mfa(MFA);
+format_reason({badarith, [MFA|_]}) ->
+ "bad arithmetic expression in function " ++ format_mfa(MFA);
+format_reason({{badmatch, Val}, [MFA|_]}) ->
+ io_lib:format("no match of right hand value ~w in ", [Val]) ++ format_mfa(MFA);
+format_reason(Reason) ->
+ {Str, _} = trunc_io:print(Reason, 500),
+ Str.
+
+format_mfa({M, F, A}) when is_list(A) ->
+ io_lib:format("~w:~w("++string:join(lists:duplicate(length(A), "~w"), ", ")++")", [M, F | A]);
+format_mfa({M, F, A}) when is_integer(A) ->
+ io_lib:format("~w:~w/~w", [M, F, A]);
format_mfa(Other) ->
- io_lib:format("~p", [Other]).
+ io_lib:format("~w", [Other]).
+
+print_silly_list(L) ->
+ case lager_stdlib:string_p(L) of
+ true -> L;
+ _ -> print_silly_list(L, [], [])
+ end.
print_silly_list([], Fmt, Acc) ->
io_lib:format(string:join(lists:reverse(Fmt), " "), lists:reverse(Acc));
print_silly_list([{K,V}|T], Fmt, Acc) ->
- print_silly_list(T, ["~p: ~p" | Fmt], [V, K | Acc]);
+ print_silly_list(T, ["~w: ~w" | Fmt], [V, K | Acc]);
print_silly_list([H|T], Fmt, Acc) ->
- print_silly_list(T, ["~p" | Fmt], [H | Acc]).
+ print_silly_list(T, ["~w" | Fmt], [H | Acc]).
View
38 src/lager.erl
@@ -19,13 +19,15 @@
-behaviour(gen_server).
%% API
--export([start_link/0,start/0,sasl_log/3, log/7, log/8, log/3, log/4, get_loglevel/1, set_loglevel/2, set_loglevel/3]).
+-export([start_link/0, start/0,
+ log/7, log/8, log/3, log/4,
+ get_loglevel/1, set_loglevel/2, set_loglevel/3]).
%% callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
code_change/3]).
--record(state, {event_pid, handler_loglevels}).
+-record(state, {event_pid, handler_loglevels, error_logger_handlers}).
%% API
@@ -52,14 +54,6 @@ start() ->
end,
gen_server:start({local, ?MODULE}, ?MODULE, [Handlers], []).
-sasl_log(ReportStr, Pid, Message) ->
- %Level = reportstr_to_level(ReportStr),
- {{Y, M, D}, {H, Mi, S}} = riak_err_stdlib:maybe_utc(erlang:localtime()),
- Msg = re:replace(binary:replace(Message, [<<"\r">>, <<"\n">>], <<>>,
- [global]), " +", " ", [global, {return, binary}]),
- io:format("~b-~b-~b ~b:~b:~b ~p ~s ~s~n", [Y, M,
- D, H, Mi, S, Pid, ReportStr, Msg]).
-
log(Level, Module, Function, Line, Pid, {{Y, M, D}, {H, Mi, S}}, Message) ->
Time = io_lib:format("~b-~b-~b ~b:~b:~b", [Y, M, D, H, Mi, S]),
Msg = io_lib:format("[~p] ~p@~p:~p:~p ~s", [Level, Pid, Module,
@@ -102,13 +96,24 @@ get_loglevel(Handler) ->
%% gen_server callbacks
init([Handlers]) ->
+ %process_flag(trap_exit, true),
%% start a gen_event linked to this process
gen_event:start_link({local, lager_event}),
%% spin up all the defined handlers
[gen_event:add_sup_handler(lager_event, Module, Args) || {Module, Args} <- Handlers],
MinLog = minimum_log_level(get_log_levels()),
lager_mochiglobal:put(loglevel, MinLog),
- {ok, #state{}}.
+ case application:get_env(lager, error_logger_redirect) of
+ {ok, true} ->
+ gen_event:add_sup_handler(error_logger, error_logger_lager_h, []),
+ %% TODO allow user to whitelist handlers to not be removed
+ Removed = [begin gen_event:delete_handler(error_logger, X, {stop_please, ?MODULE}), X end ||
+ X <- gen_event:which_handlers(error_logger) -- [error_logger_lager_h]],
+ io:format("Removed handlers ~p~n", [Removed]),
+ {ok, #state{error_logger_handlers=Removed}};
+ _ ->
+ {ok, #state{}}
+ end.
handle_call({set_loglevel, Handler, Level}, _From, State) ->
Reply = gen_event:call(lager_event, Handler, {set_loglevel, Level}),
@@ -135,14 +140,21 @@ handle_info(Info, State) ->
io:format("got info ~p~n", [Info]),
{noreply, State}.
-terminate(_Reason, _State) ->
+terminate(_Reason, #state{error_logger_handlers = Handlers}) ->
+ io:format("terminate ~p~n", Handlers),
gen_event:stop(lager_event),
+ case Handlers of
+ undefined ->
+ ok;
+ _ ->
+ io:format("Reinstalling handlers ~p~n", [Handlers]),
+ [gen_event:add_handler(error_logger, X, []) || X <- Handlers]
+ end,
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
-
%% internal functions
get_log_levels() ->
Please sign in to comment.
Something went wrong with that request. Please try again.