diff options
Diffstat (limited to 'src/couch_log/src/couch_log_formatter.erl')
-rw-r--r-- | src/couch_log/src/couch_log_formatter.erl | 442 |
1 files changed, 0 insertions, 442 deletions
diff --git a/src/couch_log/src/couch_log_formatter.erl b/src/couch_log/src/couch_log_formatter.erl deleted file mode 100644 index 4d81f184f..000000000 --- a/src/couch_log/src/couch_log_formatter.erl +++ /dev/null @@ -1,442 +0,0 @@ -% Licensed under the Apache License, Version 2.0 (the "License"); you may not -% use this file except in compliance with the License. You may obtain a copy of -% the License at -% -% http://www.apache.org/licenses/LICENSE-2.0 -% -% Unless required by applicable law or agreed to in writing, software -% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -% License for the specific language governing permissions and limitations under -% the License. -% -% @doc The formatting functions in this module are pulled -% from lager's error_logger_lager_h.erl which is available -% under the ASFv2 license. - - --module(couch_log_formatter). - - --export([ - format/4, - format/3, - format/1, - - format_reason/1, - format_mfa/1, - format_trace/1, - format_args/3 -]). - - --include("couch_log.hrl"). - - --define(DEFAULT_TRUNCATION, 1024). - - -format(Level, Pid, Fmt, Args) -> - #log_entry{ - level = couch_log_util:level_to_atom(Level), - pid = Pid, - msg = maybe_truncate(Fmt, Args), - msg_id = couch_log_util:get_msg_id(), - time_stamp = couch_log_util:iso8601_timestamp() - }. - - -format(Level, Pid, Msg) -> - #log_entry{ - level = couch_log_util:level_to_atom(Level), - pid = Pid, - msg = maybe_truncate(Msg), - msg_id = couch_log_util:get_msg_id(), - time_stamp = couch_log_util:iso8601_timestamp() - }. - - -format(Event) -> - try - do_format(Event) - catch - Tag:Err -> - Msg = "Encountered error ~w when formatting ~w", - format(error, self(), Msg, [{Tag, Err}, Event]) - end. - - -do_format({error, _GL, {Pid, "** Generic server " ++ _, Args}}) -> - %% gen_server terminate - [Name, LastMsg, State, Reason | Extra] = Args, - MsgFmt = "gen_server ~w terminated with reason: ~s~n" ++ - " last msg: ~p~n state: ~p~n extra: ~p", - MsgArgs = [Name, format_reason(Reason), LastMsg, State, Extra], - format(error, Pid, MsgFmt, MsgArgs); - -do_format({error, _GL, {Pid, "** State machine " ++ _, Args}}) -> - %% gen_fsm terminate - [Name, LastMsg, StateName, State, Reason | Extra] = Args, - MsgFmt = "gen_fsm ~w in state ~w terminated with reason: ~s~n" ++ - " last msg: ~p~n state: ~p~n extra: ~p", - MsgArgs = [Name, StateName, format_reason(Reason), LastMsg, State, Extra], - format(error, Pid, MsgFmt, MsgArgs); - -do_format({error, _GL, {Pid, "** gen_event handler" ++ _, Args}}) -> - %% gen_event handler terminate - [ID, Name, LastMsg, State, Reason] = Args, - MsgFmt = "gen_event ~w installed in ~w terminated with reason: ~s~n" ++ - " last msg: ~p~n state: ~p", - MsgArgs = [ID, Name, format_reason(Reason), LastMsg, State], - format(error, Pid, MsgFmt, MsgArgs); - -do_format({error, _GL, {emulator, "~s~n", [Msg]}}) when is_list(Msg) -> - % These messages are for whenever any process exits due - % to a throw or error. We intercept here to remove the - % extra newlines. - NewMsg = lists:sublist(Msg, length(Msg) - 1), - format(error, emulator, NewMsg); - -do_format({error, _GL, {Pid, Fmt, Args}}) -> - format(error, Pid, Fmt, Args); - -do_format({error_report, _GL, {Pid, std_error, D}}) -> - format(error, Pid, print_silly_list(D)); - -do_format({error_report, _GL, {Pid, supervisor_report, D}}) -> - case lists:sort(D) of - [{errorContext, Ctx}, {offender, Off}, - {reason, Reason}, {supervisor, Name}] -> - Offender = format_offender(Off), - MsgFmt = "Supervisor ~w had child ~s exit " ++ - "with reason ~s in context ~w", - Args = [ - supervisor_name(Name), - Offender, - format_reason(Reason), - Ctx - ], - format(error, Pid, MsgFmt, Args); - _ -> - format(error, Pid, "SUPERVISOR REPORT " ++ print_silly_list(D)) - end; - -do_format({error_report, _GL, {Pid, crash_report, [Report, Neighbors]}}) -> - Msg = "CRASH REPORT " ++ format_crash_report(Report, Neighbors), - format(error, Pid, Msg); - -do_format({warning_msg, _GL, {Pid, Fmt, Args}}) -> - format(warning, Pid, Fmt, Args); - -do_format({warning_report, _GL, {Pid, std_warning, Report}}) -> - format(warning, Pid, print_silly_list(Report)); - -do_format({info_msg, _GL, {Pid, Fmt, Args}}) -> - format(info, Pid, Fmt, Args); - -do_format({info_report, _GL, {Pid, std_info, D}}) when is_list(D) -> - case lists:sort(D) of - [{application, App}, {exited, Reason}, {type, _Type}] -> - MsgFmt = "Application ~w exited with reason: ~s", - format(info, Pid, MsgFmt, [App, format_reason(Reason)]); - _ -> - format(info, Pid, print_silly_list(D)) - end; - -do_format({info_report, _GL, {Pid, std_info, D}}) -> - format(info, Pid, "~w", [D]); - -do_format({info_report, _GL, {Pid, progress, D}}) -> - case lists:sort(D) of - [{application, App}, {started_at, Node}] -> - MsgFmt = "Application ~w started on node ~w", - format(info, Pid, MsgFmt, [App, Node]); - [{started, Started}, {supervisor, Name}] -> - MFA = format_mfa(get_value(mfargs, Started)), - ChildPid = get_value(pid, Started), - MsgFmt = "Supervisor ~w started ~s at pid ~w", - format(debug, Pid, MsgFmt, [supervisor_name(Name), MFA, ChildPid]); - _ -> - format(info, Pid, "PROGRESS REPORT " ++ print_silly_list(D)) - end; - -do_format(Event) -> - format(warning, self(), "Unexpected error_logger event ~w", [Event]). - - -format_crash_report(Report, Neighbours) -> - Pid = get_value(pid, Report), - Name = case get_value(registered_name, Report) of - undefined -> - pid_to_list(Pid); - Atom -> - io_lib:format("~s (~w)", [Atom, Pid]) - end, - {Class, Reason, Trace} = get_value(error_info, Report), - ReasonStr = format_reason({Reason, Trace}), - Type = case Class of - exit -> "exited"; - _ -> "crashed" - end, - MsgFmt = "Process ~s with ~w neighbors ~s with reason: ~s", - Args = [Name, length(Neighbours), Type, ReasonStr], - Msg = io_lib:format(MsgFmt, Args), - case filter_silly_list(Report, [pid, registered_name, error_info]) of - [] -> - Msg; - Rest -> - Msg ++ "; " ++ print_silly_list(Rest) - end. - - -format_offender(Off) -> - case get_value(mfargs, Off) of - undefined -> - %% supervisor_bridge - Args = [get_value(mod, Off), get_value(pid, Off)], - io_lib:format("at module ~w at ~w", Args); - MFArgs -> - %% regular supervisor - MFA = format_mfa(MFArgs), - - %% In 2014 the error report changed from `name' to - %% `id', so try that first. - Name = case get_value(id, Off) of - undefined -> - get_value(name, Off); - Id -> - Id - end, - Args = [Name, MFA, get_value(pid, Off)], - io_lib:format("~p started with ~s at ~w", Args) - end. - - -format_reason({'function not exported', [{M, F, A} | Trace]}) -> - ["call to unexported function ", format_mfa({M, F, A}), - " at ", format_trace(Trace)]; - -format_reason({'function not exported' = C, [{M, F, A, _Props} | Rest]}) -> - %% Drop line number from undefined function - format_reason({C, [{M, F, A} | Rest]}); - -format_reason({undef, [MFA | Trace]}) -> - ["call to undefined function ", format_mfa(MFA), - " at ", format_trace(Trace)]; - -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}) -> - ["bad return value ", print_val(Val), " at ", format_mfa(MFA)]; - -format_reason({{badrecord, Record}, Trace}) -> - ["bad record ", print_val(Record), " at ", format_trace(Trace)]; - -format_reason({{case_clause, Val}, Trace}) -> - ["no case clause matching ", print_val(Val), " at ", format_trace(Trace)]; - -format_reason({function_clause, [MFA | Trace]}) -> - ["no function clause matching ", format_mfa(MFA), - " at ", format_trace(Trace)]; - -format_reason({if_clause, Trace}) -> - ["no true branch found while evaluating if expression at ", - format_trace(Trace)]; - -format_reason({{try_clause, Val}, Trace}) -> - ["no try clause matching ", print_val(Val), " at ", format_trace(Trace)]; - -format_reason({badarith, Trace}) -> - ["bad arithmetic expression at ", format_trace(Trace)]; - -format_reason({{badmatch, Val}, Trace}) -> - ["no match of right hand value ", print_val(Val), - " at ", format_trace(Trace)]; - -format_reason({emfile, Trace}) -> - ["maximum number of file descriptors exhausted, check ulimit -n; ", - format_trace(Trace)]; - -format_reason({system_limit, [{M, F, A} | Trace]}) -> - Limit = case {M, F} of - {erlang, open_port} -> - "maximum number of ports exceeded"; - {erlang, spawn} -> - "maximum number of processes exceeded"; - {erlang, spawn_opt} -> - "maximum number of processes exceeded"; - {erlang, list_to_atom} -> - "tried to create an atom larger than 255, or maximum atom count exceeded"; - {ets, new} -> - "maximum number of ETS tables exceeded"; - _ -> - format_mfa({M, F, A}) - end, - ["system limit: ", Limit, " at ", format_trace(Trace)]; - -format_reason({badarg, [MFA | Trace]}) -> - ["bad argument in call to ", format_mfa(MFA), - " at ", format_trace(Trace)]; - -format_reason({{badarg, Stack}, _}) -> - format_reason({badarg, Stack}); - -format_reason({{badarity, {Fun, Args}}, Trace}) -> - {arity, Arity} = lists:keyfind(arity, 1, erlang:fun_info(Fun)), - MsgFmt = "function called with wrong arity of ~w instead of ~w at ", - [io_lib:format(MsgFmt, [length(Args), Arity]), format_trace(Trace)]; - -format_reason({noproc, MFA}) -> - ["no such process or port in call to ", format_mfa(MFA)]; - -format_reason({{badfun, Term}, Trace}) -> - ["bad function ", print_val(Term), " called at ", format_trace(Trace)]; - -format_reason({Reason, [{M, F, A} | _] = Trace}) - when is_atom(M), is_atom(F), is_integer(A) -> - [format_reason(Reason), " at ", format_trace(Trace)]; - -format_reason({Reason, [{M, F, A} | _] = Trace}) - when is_atom(M), is_atom(F), is_list(A) -> - [format_reason(Reason), " at ", format_trace(Trace)]; - -format_reason({Reason, [{M, F, A, Props} | _] = Trace}) - when is_atom(M), is_atom(F), is_integer(A), is_list(Props) -> - [format_reason(Reason), " at ", format_trace(Trace)]; - -format_reason({Reason, [{M, F, A, Props} | _] = Trace}) - when is_atom(M), is_atom(F), is_list(A), is_list(Props) -> - [format_reason(Reason), " at ", format_trace(Trace)]; - -format_reason(Reason) -> - {Str, _} = couch_log_trunc_io:print(Reason, 500), - Str. - - -format_mfa({M, F, A}) when is_list(A) -> - {FmtStr, Args} = format_args(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 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(Trace) when is_list(Trace) -> - format_trace(Trace); - -format_mfa(Other) -> - io_lib:format("~w", [Other]). - - -format_trace([MFA]) -> - [trace_mfa(MFA)]; - -format_trace([MFA | Rest]) -> - [trace_mfa(MFA), " <= ", format_trace(Rest)]; - -format_trace(Other) -> - io_lib:format("~w", [Other]). - - -trace_mfa({M, F, A}) when is_list(A) -> - format_mfa({M, F, length(A)}); - -trace_mfa({M, F, A, Props}) when is_list(A) -> - format_mfa({M, F, length(A), Props}); - -trace_mfa(Other) -> - format_mfa(Other). - - -format_args([], FmtAcc, ArgsAcc) -> - {string:join(lists:reverse(FmtAcc), ", "), lists:reverse(ArgsAcc)}; - -format_args([H|T], FmtAcc, ArgsAcc) -> - {Str, _} = couch_log_trunc_io:print(H, 100), - format_args(T, ["~s" | FmtAcc], [Str | ArgsAcc]). - - -maybe_truncate(Fmt, Args) -> - MaxMsgSize = couch_log_config:get(max_message_size), - couch_log_trunc_io:format(Fmt, Args, MaxMsgSize). - - -maybe_truncate(Msg) -> - MaxMsgSize = couch_log_config:get(max_message_size), - case iolist_size(Msg) > MaxMsgSize of - true -> - MsgBin = iolist_to_binary(Msg), - PrefixSize = MaxMsgSize - 3, - <<Prefix:PrefixSize/binary, _/binary>> = MsgBin, - [Prefix, "..."]; - false -> - Msg - end. - - -print_silly_list(L) when is_list(L) -> - case couch_log_util:string_p(L) of - true -> - couch_log_trunc_io:format("~s", [L], ?DEFAULT_TRUNCATION); - _ -> - print_silly_list(L, [], []) - end; - -print_silly_list(L) -> - {Str, _} = couch_log_trunc_io:print(L, ?DEFAULT_TRUNCATION), - Str. - - -print_silly_list([], Fmt, Acc) -> - couch_log_trunc_io:format(string:join(lists:reverse(Fmt), ", "), - lists:reverse(Acc), ?DEFAULT_TRUNCATION); - -print_silly_list([{K, V} | T], Fmt, Acc) -> - print_silly_list(T, ["~p: ~p" | Fmt], [V, K | Acc]); - -print_silly_list([H | T], Fmt, Acc) -> - print_silly_list(T, ["~p" | Fmt], [H | Acc]). - - -print_val(Val) -> - {Str, _} = couch_log_trunc_io:print(Val, 500), - Str. - - -filter_silly_list([], _) -> - []; - -filter_silly_list([{K, V} | T], Filter) -> - case lists:member(K, Filter) of - true -> - filter_silly_list(T, Filter); - false -> - [{K, V} | filter_silly_list(T, Filter)] - end; - -filter_silly_list([H | T], Filter) -> - [H | filter_silly_list(T, Filter)]. - - -get_value(Key, Value) -> - get_value(Key, Value, undefined). - -get_value(Key, List, Default) -> - case lists:keyfind(Key, 1, List) of - false -> Default; - {Key, Value} -> Value - end. - -supervisor_name({local, Name}) -> Name; -supervisor_name(Name) -> Name. |