log4erl是一个在Erlang下很好的处理log的tools。可是,一些系统崩溃的error_msg不能用log4erl直接捕捉。因为OTP系统默认的error处理是给error_logger的。
可是系统崩溃的log对于debug和improve来说至关重要。一开始,我是一面用log4erl,一面用error_logger:logfile({open, FileName})来分别记录我自己定义的log和捕捉系统崩溃时的log。
之前,就有听说过error_logger可以自己写callback module然后add_report_handler。可是,之前一直没有时间去看,这个callback module的具体要求和格式。
今天发现了log4erl下面原来已经提供了这个callback module:error_logger_log4erl_h,所以,这一切都变得很简单。只要:
error_logger:add_report_handler(error_logger_log4erl_h).
就可以,转给log4erl来记录相应的系统发出的log了。
看了一下,error_logger_log4erl_h的源代码,发现原来就是这么简单地mapping一下就可以了:
-module(error_logger_log4erl_h).
-behaviour(gen_event).
...
-record(elogger_l4e_mappings, {error=error, info_msg=info, warning_msg=warn,
error_report=error, info_report=info,
warning_report=warn}).
...
init([])->
{ok, #elogger_l4e_mappings{}};
init(Conf) ->
io:format("Conf ~p~n",[Conf]),
{ok, mapping(Conf, #elogger_l4e_mappings{})}.
...
handle_event({error, _GLeader, {_PID, Msg, Data}}, #elogger_l4e_mappings{error=L} = State) ->
R = log4erl:log(L, Msg, Data),
{R, State};
handle_event({info_msg, _GLeader, {_PID, Msg, Data}}, #elogger_l4e_mappings{info_msg=L} = State) ->
R = log4erl:log(L, Msg, Data),
{R, State};
handle_event({warning_msg, _GLeader, {_PID, Msg, Data}}, #elogger_l4e_mappings{warning_msg=L} = State) ->
R = log4erl:log(L, Msg, Data),
{R, State};
handle_event({error_report, _GLeader, _}, State) ->
{ok, State};
handle_event({info_report, _GLeader, _}, State) ->
{ok, State};
handle_event({warning_report, _GLeader, _}, State) ->
{ok, State}.
...