From 04792f1b8aef41f5011d71851855fc9336f5a9d2 Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Tue, 28 Jun 2011 14:49:04 -0400 Subject: [PATCH] Initial version of error_logger->lager translator --- src/error_logger_lager_h.erl | 111 +++++++++++++++++++++++++++++++++++ src/lager.erl | 16 ++++- src/lager_stdlib.erl | 51 ++++++++++++++++ 3 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 src/error_logger_lager_h.erl create mode 100644 src/lager_stdlib.erl diff --git a/src/error_logger_lager_h.erl b/src/error_logger_lager_h.erl new file mode 100644 index 0000000..7501282 --- /dev/null +++ b/src/error_logger_lager_h.erl @@ -0,0 +1,111 @@ +%% Copyright (c) 2011 Basho Technologies, Inc. All Rights Reserved. +%% +%% This file is provided to you 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. + +-module(error_logger_lager_h). + +-behaviour(gen_event). + +-export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, + code_change/3]). + +init(_) -> + {ok, {}}. + +handle_call(_Request, State) -> + {ok, ok, 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); + {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 REPORT" ++ print_silly_list(D)) + end; + {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, print_silly_list(D)) + end; + {info_report, _GL, {P, progress, D}} -> + Details = lists:sort(D), + case Details of + [{application, App}, {started_at, Node}] -> + lager:log(info, P, "Application ~p started on node ~p", + [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, "PROGRESS REPORT" ++ print_silly_list(D)) + end; + _ -> + io:format("Event ~p~n", [Event]) + end, + {ok, State}. + +handle_info(_Info, State) -> + {ok, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%% internal functions + +print_silly_list(L) -> + case lager_stdlib:string_p(L) of + true -> L; + _ -> print_silly_list(L, [], []) + end. + +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)]); + 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)]) + end. + +format_mfa({M, F, A}) -> + %% TODO pretty-print args better + io_lib:format("~p:~p(~p)", [M, F, A]); +format_mfa(Other) -> + io_lib:format("~p", [Other]). + +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([H|T], Fmt, Acc) -> + print_silly_list(T, ["~p" | Fmt], [H | Acc]). diff --git a/src/lager.erl b/src/lager.erl index 787bfdb..29b9b47 100644 --- a/src/lager.erl +++ b/src/lager.erl @@ -19,7 +19,7 @@ -behaviour(gen_server). %% API --export([start_link/0,start/0,sasl_log/3, log/7, log/8, get_loglevel/1, set_loglevel/2, set_loglevel/3]). +-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]). %% callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, @@ -72,6 +72,20 @@ log(Level, Module, Function, Line, Pid, {{Y, M, D}, {H, Mi, S}}, Format, Args) - Function, Line, io_lib:format(Format, Args)]), gen_event:sync_notify(lager_event, {log, lager_util:level_to_num(Level), Time, Msg}). +log(Level, Pid, Message) -> + {{Y, M, D}, {H, Mi, S}} = riak_err_stdlib:maybe_utc(erlang:localtime()), + Time = io_lib:format("~b-~b-~b ~b:~b:~b", [Y, M, D, H, Mi, S]), + Msg = io_lib:format("[~p] ~p ~s", [Level, Pid, Message]), + gen_event:sync_notify(lager_event, {log, lager_util:level_to_num(Level), + Time, Msg}). + +log(Level, Pid, Format, Args) -> + {{Y, M, D}, {H, Mi, S}} = riak_err_stdlib:maybe_utc(erlang:localtime()), + Time = io_lib:format("~b-~b-~b ~b:~b:~b", [Y, M, D, H, Mi, S]), + Msg = io_lib:format("[~p] ~p ~s", [Level, Pid, io_lib:format(Format, Args)]), + gen_event:sync_notify(lager_event, {log, lager_util:level_to_num(Level), + Time, Msg}). + set_loglevel(Handler, Level) when is_atom(Level) -> gen_server:call(?MODULE, {set_loglevel, Handler, Level}). diff --git a/src/lager_stdlib.erl b/src/lager_stdlib.erl new file mode 100644 index 0000000..0de67a9 --- /dev/null +++ b/src/lager_stdlib.erl @@ -0,0 +1,51 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% @doc Functions from Erlang OTP distribution that are really useful +%% but aren't exported. +%% +%% All functions in this module are covered by the Erlang/OTP source +%% distribution's license, the Erlang Public License. See +%% http://www.erlang.org/ for full details. + +-module(lager_stdlib). + +-export([string_p/1]). + +string_p([]) -> + false; +string_p(Term) -> + string_p1(Term). + +string_p1([H|T]) when is_integer(H), H >= $\s, H < 255 -> + string_p1(T); +string_p1([$\n|T]) -> string_p1(T); +string_p1([$\r|T]) -> string_p1(T); +string_p1([$\t|T]) -> string_p1(T); +string_p1([$\v|T]) -> string_p1(T); +string_p1([$\b|T]) -> string_p1(T); +string_p1([$\f|T]) -> string_p1(T); +string_p1([$\e|T]) -> string_p1(T); +string_p1([H|T]) when is_list(H) -> + case string_p1(H) of + true -> string_p1(T); + _ -> false + end; +string_p1([]) -> true; +string_p1(_) -> false.