erlang应用都会启动一个sasl应用,sasl的一个重要功能便是可以记录系统进程相关日志,如进程启动、结束、崩溃错误等信息。sasl的日志功能是基于erlang自带的日志模块error_logger来实现的. sasl中定义了下面3个错误处理:
error_logger_mf_h :循环日志文件记录
在sasl.erl模块中注册了日志处理句柄,可以找到代码片断
从上面的代码可以看出sasl会处理supervisor_report、crash_report类型的标准错误报告,以及progress类型的信息,对于指定了类型的标准错误报告,默认的错误处理句柄是不会处理的。
我们可以模拟一下进程启动的输出日志
sasl_report_tty_h : 将日志输出到控制台 .
sasl_report_file_h : 将日志输出到单个文件error_logger_mf_h :循环日志文件记录
elog.config
%% rotating log and minimal tty
[{sasl, [
{sasl_error_logger, false},
%% define the parameters of the rotating log
%% the log file directory
{error_logger_mf_dir,"/home/joe/error_logs" },
%% # bytes per logfile
{error_logger_mf_maxbytes,10485760}, % 10 MB
%% maximum number of logfiles
{error_logger_mf_maxfiles, 10}
]}].
$erl -boot start_sasl -config elog
在sasl.erl模块中注册了日志处理句柄,可以找到代码片断
......
add_sasl_error_logger(undefined, _Type) -> ok;
add_sasl_error_logger(Handler, Type) ->
error_logger:add_report_handler(mod(Handler), args(Handler, Type)).
......
add_error_logger_mf(undefined) -> ok;
add_error_logger_mf({Dir, MaxB, MaxF}) ->
error_logger:add_report_handler(
log_mf_h, log_mf_h:init(Dir, MaxB, MaxF, fun pred/1)).
在模块sasl_report.erl中可以找到处理输出的代码:
is_my_error_report(all, Type) -> is_my_error_report(Type);
is_my_error_report(error, Type) -> is_my_error_report(Type);
is_my_error_report(_, _Type) -> false.
is_my_error_report(supervisor_report) -> true;
is_my_error_report(crash_report) -> true;
is_my_error_report(_) -> false.
is_my_info_report(all, Type) -> is_my_info_report(Type);
is_my_info_report(progress, Type) -> is_my_info_report(Type);
is_my_info_report(_, _Type) -> false.
is_my_info_report(progress) -> true;
is_my_info_report(_) -> false.
write_report2(IO, Fd, Head, supervisor_report, Report) ->
Name = sup_get(supervisor, Report),
Context = sup_get(errorContext, Report),
Reason = sup_get(reason, Report),
Offender = sup_get(offender, Report),
FmtString = " Supervisor: ~p~n Context: ~p~n Reason: "
"~80.18p~n Offender: ~80.18p~n~n",
write_report_action(IO, Fd, Head ++ FmtString,
[Name,Context,Reason,Offender]);
write_report2(IO, Fd, Head, progress, Report) ->
Format = format_key_val(Report),
write_report_action(IO, Fd, Head ++ "~s", [Format]);
write_report2(IO, Fd, Head, crash_report, Report) ->
Format = proc_lib:format(Report),
write_report_action(IO, Fd, Head ++ "~s", [Format]).
从上面的代码可以看出sasl会处理supervisor_report、crash_report类型的标准错误报告,以及progress类型的信息,对于指定了类型的标准错误报告,默认的错误处理句柄是不会处理的。
我们可以模拟一下进程启动的输出日志
C:\Users\Administrator>erl -boot start_sasl
=PROGRESS REPORT==== 15-Aug-2013::23:17:28 ===
supervisor: {local,sasl_safe_sup}
started: [{pid,<0.33.0>},
{name,alarm_handler},
{mfargs,{alarm_handler,start_link,[]
{restart_type,permanent},
{shutdown,2000},
{child_type,worker}]
......
1> error_logger:info_report(progress,[{application,test},{started_at, nonode@noh
ost}]).
=PROGRESS REPORT==== 15-Aug-2013::23:19:45 ===
application: test
started_at: nonode@nohost
ok
查看日志处理句柄
3> gen_event:which_handlers(error_logger).
[sasl_report_tty_h,error_logger,error_logger_tty_h]