Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 250 lines (224 sloc) 9.915 kb
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
1 %% Copyright (c) 2011 Basho Technologies, Inc. All Rights Reserved.
2 %%
3 %% This file is provided to you under the Apache License,
4 %% Version 2.0 (the "License"); you may not use this file
5 %% except in compliance with the License. You may obtain
6 %% a copy of the License at
7 %%
8 %% http://www.apache.org/licenses/LICENSE-2.0
9 %%
10 %% Unless required by applicable law or agreed to in writing,
11 %% software distributed under the License is distributed on an
12 %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13 %% KIND, either express or implied. See the License for the
14 %% specific language governing permissions and limitations
15 %% under the License.
16
862a9cb Andrew Thompson Documentation!
Vagabond authored
17 %% @doc A error_logger backend for redirecting events into lager.
18 %% Error messages and crash logs are also optionally written to a crash log.
19
20 %% @see lager_crash_log
21
22 %% @private
23
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
24 -module(error_logger_lager_h).
25
886d410 Andrew Thompson Make highest log level be 0; add some helper macros
Vagabond authored
26 -include("lager.hrl").
27
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
28 -behaviour(gen_event).
29
30 -export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2,
31 code_change/3]).
32
1f3493d Andrew Thompson Restart error_logger handler if it exits, cleanups
Vagabond authored
33 -export([format_reason/1]).
34
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
35 -define(LOG(Level, Pid, Msg),
886d410 Andrew Thompson Make highest log level be 0; add some helper macros
Vagabond authored
36 case ?SHOULD_LOG(Level) of
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
37 true ->
38 lager:log(Level, Pid, Msg);
39 _ -> ok
40 end).
41
42 -define(LOG(Level, Pid, Fmt, Args),
886d410 Andrew Thompson Make highest log level be 0; add some helper macros
Vagabond authored
43 case ?SHOULD_LOG(Level) of
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
44 true ->
45 lager:log(Level, Pid, Fmt, Args);
46 _ -> ok
47 end).
48
fed1103 Andrew Thompson Add a crash.log logger, based on riak_err, that logs error reports in mo...
Vagabond authored
49 -define(CRASH_LOG(Event),
50 gen_server:cast(lager_crash_log, {log, Event})).
51
ec61e88 Andrew Thompson Make the dialyzer happy.
Vagabond authored
52 -spec init(any()) -> {ok, {}}.
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
53 init(_) ->
54 {ok, {}}.
55
56 handle_call(_Request, State) ->
57 {ok, ok, State}.
58
59 handle_event(Event, State) ->
60 case Event of
61 {error, _GL, {Pid, Fmt, Args}} ->
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
62 case Fmt of
63 "** Generic server "++_ ->
64 %% gen_server terminate
65 [Name, _Msg, _State, Reason] = Args,
fed1103 Andrew Thompson Add a crash.log logger, based on riak_err, that logs error reports in mo...
Vagabond authored
66 ?CRASH_LOG(Event),
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
67 ?LOG(error, Pid, "gen_server ~w terminated with reason: ~s",
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
68 [Name, format_reason(Reason)]);
69 "** State machine "++_ ->
70 %% gen_fsm terminate
71 [Name, _Msg, StateName, _StateData, Reason] = Args,
fed1103 Andrew Thompson Add a crash.log logger, based on riak_err, that logs error reports in mo...
Vagabond authored
72 ?CRASH_LOG(Event),
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
73 ?LOG(error, Pid, "gen_fsm ~w in state ~w terminated with reason: ~s",
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
74 [Name, StateName, format_reason(Reason)]);
75 "** gen_event handler"++_ ->
76 %% gen_event handler terminate
77 [ID, Name, _Msg, _State, Reason] = Args,
fed1103 Andrew Thompson Add a crash.log logger, based on riak_err, that logs error reports in mo...
Vagabond authored
78 ?CRASH_LOG(Event),
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
79 ?LOG(error, Pid, "gen_event ~w installed in ~w terminated with reason: ~s",
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
80 [ID, Name, format_reason(Reason)]);
81 _ ->
fed1103 Andrew Thompson Add a crash.log logger, based on riak_err, that logs error reports in mo...
Vagabond authored
82 ?CRASH_LOG(Event),
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
83 ?LOG(error, Pid, Fmt, Args)
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
84 end;
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
85 {error_report, _GL, {Pid, std_error, D}} ->
fed1103 Andrew Thompson Add a crash.log logger, based on riak_err, that logs error reports in mo...
Vagabond authored
86 ?CRASH_LOG(Event),
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
87 ?LOG(error, Pid, print_silly_list(D));
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
88 {error_report, _GL, {Pid, supervisor_report, D}} ->
fed1103 Andrew Thompson Add a crash.log logger, based on riak_err, that logs error reports in mo...
Vagabond authored
89 ?CRASH_LOG(Event),
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
90 case lists:sort(D) of
91 [{errorContext, Ctx}, {offender, Off}, {reason, Reason}, {supervisor, Name}] ->
92 Offender = format_offender(Off),
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
93 ?LOG(error, Pid, "Supervisor ~w had child ~s exit with reason ~w in context ~w", [element(2, Name), Offender, Reason, Ctx]);
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
94 _ ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
95 ?LOG(error, Pid, ["SUPERVISOR REPORT ", print_silly_list(D)])
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
96 end;
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
97 {error_report, _GL, {Pid, crash_report, [Self, Neighbours]}} ->
fed1103 Andrew Thompson Add a crash.log logger, based on riak_err, that logs error reports in mo...
Vagabond authored
98 ?CRASH_LOG(Event),
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
99 ?LOG(error, Pid, ["CRASH REPORT ", format_crash_report(Self, Neighbours)]);
5b9a4c6 Andrew Thompson Support warning messages, put commas between terms in report messages
Vagabond authored
100 {warning_msg, _GL, {Pid, Fmt, Args}} ->
101 ?LOG(warning, Pid, Fmt, Args);
102 {warning_report, _GL, {Pid, std_warning, Report}} ->
103 ?LOG(warning, Pid, print_silly_list(Report));
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
104 {info_msg, _GL, {Pid, Fmt, Args}} ->
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
105 ?LOG(info, Pid, Fmt, Args);
e9abf79 Andrew Thompson Handle 'single term' error_logger reports
Vagabond authored
106 {info_report, _GL, {Pid, std_info, D}} when is_list(D) ->
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
107 Details = lists:sort(D),
108 case Details of
109 [{application, App}, {exited, Reason}, {type, _Type}] ->
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
110 ?LOG(info, Pid, "Application ~w exited with reason: ~w", [App, Reason]);
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
111 _ ->
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
112 ?LOG(info, Pid, print_silly_list(D))
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
113 end;
e9abf79 Andrew Thompson Handle 'single term' error_logger reports
Vagabond authored
114 {info_report, _GL, {Pid, std_info, D}} ->
115 ?LOG(info, Pid, "~w", [D]);
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
116 {info_report, _GL, {P, progress, D}} ->
117 Details = lists:sort(D),
118 case Details of
119 [{application, App}, {started_at, Node}] ->
399e43f Andrew Thompson Check threshold when generating messages from error_logger
Vagabond authored
120 ?LOG(info, P, "Application ~w started on node ~w",
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
121 [App, Node]);
122 [{started, Started}, {supervisor, Name}] ->
123 MFA = format_mfa(proplists:get_value(mfargs, Started)),
124 Pid = proplists:get_value(pid, Started),
c738bf3 Andrew Thompson Supervisor startup should be debug level
Vagabond authored
125 ?LOG(debug, P, "Supervisor ~w started ~s at pid ~w", [element(2, Name), MFA, Pid]);
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
126 _ ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
127 ?LOG(info, P, ["PROGRESS REPORT ", print_silly_list(D)])
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
128 end;
129 _ ->
af2f220 Andrew Thompson Log unexpected error_logger messages to lager
Vagabond authored
130 ?LOG(warning, self(), "Unexpected error_logger event ~w", [Event])
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
131 end,
132 {ok, State}.
133
134 handle_info(_Info, State) ->
135 {ok, State}.
136
137 terminate(_Reason, _State) ->
138 ok.
139
140 code_change(_OldVsn, State, _Extra) ->
141 {ok, State}.
142
143 %% internal functions
144
1f3493d Andrew Thompson Restart error_logger handler if it exits, cleanups
Vagabond authored
145 format_crash_report(Report, Neighbours) ->
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
146 Name = proplists:get_value(registered_name, Report, proplists:get_value(pid, Report)),
147 {_Class, Reason, _Trace} = proplists:get_value(error_info, Report),
1f3493d Andrew Thompson Restart error_logger handler if it exits, cleanups
Vagabond authored
148 io_lib:format("Process ~w with ~w neighbours crashed with reason: ~s", [Name, length(Neighbours), format_reason(Reason)]).
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
149
150 format_offender(Off) ->
151 case proplists:get_value(name, Off) of
152 undefined ->
153 %% supervisor_bridge
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
154 io_lib:format("at module ~w at ~w", [proplists:get_value(mod, Off), proplists:get_value(pid, Off)]);
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
155 Name ->
156 %% regular supervisor
157 MFA = format_mfa(proplists:get_value(mfargs, Off)),
83ed81e Andrew Thompson Tests for error_logger:error_msg and friends
Vagabond authored
158 io_lib:format("~w started with ~s at ~w", [Name, MFA, proplists:get_value(pid, Off)])
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
159 end.
160
7696cc9 Andrew Thompson More tests
Vagabond authored
161 format_reason({'function not exported', [{M, F, A},MFA|_]}) ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
162 ["call to undefined function ", format_mfa({M, F, length(A)}), " from ", format_mfa(MFA)];
900aaca Andrew Thompson Formatters for a bunch more common exceptions
Vagabond authored
163 format_reason({undef, [MFA|_]}) ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
164 ["call to undefined function ", format_mfa(MFA)];
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
165 format_reason({bad_return_value, Val}) ->
166 io_lib:format("bad return value: ~w", [Val]);
900aaca Andrew Thompson Formatters for a bunch more common exceptions
Vagabond authored
167 format_reason({{case_clause, Val}, [MFA|_]}) ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
168 [io_lib:format("no case clause matching ~w in ", [Val]), format_mfa(MFA)];
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
169 format_reason({function_clause, [MFA|_]}) ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
170 ["no function clause matching ", format_mfa(MFA)];
900aaca Andrew Thompson Formatters for a bunch more common exceptions
Vagabond authored
171 format_reason({if_clause, [MFA|_]}) ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
172 ["no true branch found while evaluating if expression in ", format_mfa(MFA)];
900aaca Andrew Thompson Formatters for a bunch more common exceptions
Vagabond authored
173 format_reason({{try_clause, Val}, [MFA|_]}) ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
174 [io_lib:format("no try clause matching ~w in ", [Val]), format_mfa(MFA)];
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
175 format_reason({badarith, [MFA|_]}) ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
176 ["bad arithmetic expression in ", format_mfa(MFA)];
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
177 format_reason({{badmatch, Val}, [MFA|_]}) ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
178 [io_lib:format("no match of right hand value ~w in ", [Val]), format_mfa(MFA)];
a6325a7 Andrew Thompson Add formatting for emfile and for various system limits
Vagabond authored
179 format_reason({emfile, _Trace}) ->
180 "maximum number of file descriptors exhausted, check ulimit -n";
181 format_reason({system_limit, [{M, F, _}|_] = Trace}) ->
182 Limit = case {M, F} of
183 {erlang, open_port} ->
184 "maximum number of ports exceeded";
185 {erlang, spawn} ->
186 "maximum number of processes exceeded";
187 {erlang, spawn_opt} ->
188 "maximum number of processes exceeded";
189 {erlang, list_to_atom} ->
190 "tried to create an atom larger than 255, or maximum atom count exceeded";
157d676 Andrew Thompson Handle ETS table count system limit
Vagabond authored
191 {ets, new} ->
192 "maximum number of ETS tables exceeded";
a6325a7 Andrew Thompson Add formatting for emfile and for various system limits
Vagabond authored
193 _ ->
4ac0137 Andrew Thompson Rename trunc_io to lager_trunc_io to prevent clashes
Vagabond authored
194 {Str, _} = lager_trunc_io:print(Trace, 500),
a6325a7 Andrew Thompson Add formatting for emfile and for various system limits
Vagabond authored
195 Str
196 end,
197 ["system limit: ", Limit];
7696cc9 Andrew Thompson More tests
Vagabond authored
198 format_reason({badarg, [MFA,MFA2|_]}) ->
900aaca Andrew Thompson Formatters for a bunch more common exceptions
Vagabond authored
199 case MFA of
7696cc9 Andrew Thompson More tests
Vagabond authored
200 {_M, _F, A} when is_list(A) ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
201 ["bad argument in call to ", format_mfa(MFA), " in ", format_mfa(MFA2)];
900aaca Andrew Thompson Formatters for a bunch more common exceptions
Vagabond authored
202 _ ->
203 %% seems to be generated by a bad call to a BIF
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
204 ["bad argument in ", format_mfa(MFA)]
900aaca Andrew Thompson Formatters for a bunch more common exceptions
Vagabond authored
205 end;
206 format_reason({{badarity, {Fun, Args}}, [MFA|_]}) ->
207 {arity, Arity} = lists:keyfind(arity, 1, erlang:fun_info(Fun)),
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
208 [io_lib:format("fun called with wrong arity of ~w instead of ~w in ", [length(Args), Arity]), format_mfa(MFA)];
900aaca Andrew Thompson Formatters for a bunch more common exceptions
Vagabond authored
209 format_reason({noproc, MFA}) ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
210 ["no such process or port in call to ", format_mfa(MFA)];
6916a66 Andrew Thompson Added badfun support, and tests for progress reports
Vagabond authored
211 format_reason({{badfun, Term}, [MFA|_]}) ->
10153cf Andrew Thompson Optimize list construction, somewhat
Vagabond authored
212 [io_lib:format("bad function ~w in ", [Term]), format_mfa(MFA)];
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
213 format_reason(Reason) ->
4ac0137 Andrew Thompson Rename trunc_io to lager_trunc_io to prevent clashes
Vagabond authored
214 {Str, _} = lager_trunc_io:print(Reason, 500),
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
215 Str.
216
217 format_mfa({M, F, A}) when is_list(A) ->
7e68976 Andrew Thompson Try to improve M:F(A) printing a little
Vagabond authored
218 io_lib:format("~w:~w("++format_args(A, [])++")", [M, F | A]);
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
219 format_mfa({M, F, A}) when is_integer(A) ->
220 io_lib:format("~w:~w/~w", [M, F, A]);
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
221 format_mfa(Other) ->
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
222 io_lib:format("~w", [Other]).
223
7e68976 Andrew Thompson Try to improve M:F(A) printing a little
Vagabond authored
224 format_args([], Acc) ->
225 string:join(lists:reverse(Acc), ", ");
226 format_args([H|T], Acc) when is_list(H) ->
227 case lager_stdlib:string_p(H) of
228 true ->
229 format_args(T, ["\"~s\""|Acc]);
230 _ ->
231 format_args(T, ["~w"|Acc])
232 end;
233 format_args([_|T], Acc) ->
234 format_args(T, ["~w"|Acc]).
235
e9abf79 Andrew Thompson Handle 'single term' error_logger reports
Vagabond authored
236 print_silly_list(L) when is_list(L) ->
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
237 case lager_stdlib:string_p(L) of
238 true -> L;
239 _ -> print_silly_list(L, [], [])
e9abf79 Andrew Thompson Handle 'single term' error_logger reports
Vagabond authored
240 end;
241 print_silly_list(L) ->
242 io_lib:format("~w", [L]).
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
243
244 print_silly_list([], Fmt, Acc) ->
5b9a4c6 Andrew Thompson Support warning messages, put commas between terms in report messages
Vagabond authored
245 io_lib:format(string:join(lists:reverse(Fmt), ", "), lists:reverse(Acc));
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
246 print_silly_list([{K,V}|T], Fmt, Acc) ->
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
247 print_silly_list(T, ["~w: ~w" | Fmt], [V, K | Acc]);
04792f1 Andrew Thompson Initial version of error_logger->lager translator
Vagabond authored
248 print_silly_list([H|T], Fmt, Acc) ->
b7a5648 Andrew Thompson A bunch more work on the error_logger interop
Vagabond authored
249 print_silly_list(T, ["~w" | Fmt], [H | Acc]).
Something went wrong with that request. Please try again.