erlang日志系统

  本文章目的是解决产品化环境下,将日志输出到日志文件而不在erlang shell终端中显示,方便在shell中执行调试函数!

1、sasl

  sasl提供错误日志,系统过载保护等,它有定义了下面三个日志处理器

    sasl_report_tty_h : 将日志输出到控制台 

    sasl_report_file_h : 将日志输出到单个文件 

    error_logger_mf_h :循环日志文件记录

   sasl启动配置文件elog.config 如下

 

[{sasl,   
    [{sasl_error_logger, false},  
     {errlog_type, error},  
  
     {error_logger_mf_dir, "/data/sasl/log"},  
     {error_logger_mf_maxbytes, 10485760},  
     {error_logger_maxfiles, 10}  
    ]  
}]. 

    {sasl_error_logger,false}表示错误信息不会输出到控制台(看sasl.erl代码)

    {sasl_error_logger,tty} 表示错误信息输出到控制台(默认情况下也是输出到控制台)

    {sasl_error_logger,{file,"../log/test.log"} 表示错误信息写到单一文件test.log

    {errorlog_type,error} 表示只输出error信息,也可以是info,warnning等

    {error_logger_mf_dir,"data/sasl/log"} 表示输出到循环日志文件log

sasl.erl 代码内容

start(_, []) ->
    Handler = get_sasl_error_logger(),
    Type = get_sasl_error_logger_type(),
    Mf = get_error_logger_mf(),
    add_sasl_error_logger(Handler, Type),
    add_error_logger_mf(Mf),
    State = #state{sasl_error_logger = Handler, error_logger_mf = Mf}, 
    case supervisor:start_link({local, sasl_sup}, sasl, []) of
	{ok, Pid} -> {ok, Pid, State};
	Error -> Error
    end.

...

get_sasl_error_logger() ->
    case application:get_env(sasl, sasl_error_logger) of
	{ok, false} -> undefined;
	{ok, tty} -> tty;
	{ok, {file, File}} when is_list(File) -> {file, File, [write]};
	{ok, {file, File, Modes}} when is_list(File), is_list(Modes) ->
        {file, File, Modes};
	{ok, Bad} -> exit({bad_config, {sasl, {sasl_error_logger, Bad}}});
	_ -> undefined
    end.

get_sasl_error_logger_type() ->
    case application:get_env(sasl, errlog_type) of
	{ok, error} -> error;
	{ok, progress} -> progress;
	{ok, all} -> all;
	{ok, Bad} -> exit({bad_config, {sasl, {errlog_type, Bad}}});
	_ -> all
    end.

get_error_logger_mf() ->
    case catch get_mf() of
	{'EXIT', Reason} ->
	    exit(Reason);
	Mf ->
	    Mf
    end.

get_mf() -> 
    Dir = get_mf_dir(),
    MaxB = get_mf_maxb(),
    MaxF = get_mf_maxf(),
    case {Dir, MaxB, MaxF} of
	{undefined,undefined,undefined} ->
	    undefined;
	{undefined,_,_} ->
	    exit({missing_config, {sasl, error_logger_mf_dir}});
	{_,undefined,_} ->
	    exit({missing_config, {sasl, error_logger_mf_maxbytes}});
	{_,_,undefined} ->
	    exit({missing_config, {sasl, error_logger_mf_maxfiles}});
	R ->
	    R
    end.

get_mf_dir() ->
    case application:get_env(sasl, error_logger_mf_dir) of
	{ok, false} -> undefined;
	{ok, Dir} when is_list(Dir) -> Dir;
	undefined -> undefined;
	{ok, Bad} -> exit({bad_config, {sasl, {error_logger_mf_dir, Bad}}})
    end.

get_mf_maxb() ->
    case application:get_env(sasl, error_logger_mf_maxbytes) of
	{ok, MaxB} when is_integer(MaxB) -> MaxB;
	undefined -> undefined;
	{ok, Bad} -> exit({bad_config, {sasl, {error_logger_mf_maxbytes, Bad}}})
    end.

get_mf_maxf() ->
    case application:get_env(sasl, error_logger_mf_maxfiles) of
	{ok, MaxF} when is_integer(MaxF), MaxF > 0, MaxF < 256 -> MaxF;
	undefined -> undefined;
	{ok, Bad} -> exit({bad_config, {sasl, {error_logger_mf_maxfiles, Bad}}})
    end.

erl -boot start_sasl -config elog

%% 查看handler

gen_event:which_handlers(error_logger).
[log_mf_h,error_logger,error_logger_tty_h]
]

问题来了,明明设了{sasl_error_logger,false},handler列表中为啥error_logger_tty_h还存在呢? 下面再看一下kernel模块

2、kernel

kernel.app 部分配置如下

error_logger,
file_server_2,
fixtable_server,
global_group,
global_name_server,
heart,
init,
kernel_config,
kernel_sup,
net_kernel,
net_sup,
rex,
user,
os_server,
ddll_server,
erl_epmd,
inet_db,
pg2]},
{applications, []},
{env, [{error_logger, tty}]},

kernel.erl部分源码

start(_, []) ->
    case supervisor:start_link({local, kernel_sup}, kernel, []) of
	{ok, Pid} ->
            %% add signal handler
            case whereis(erl_signal_server) of
                %% in case of minimal mode
                undefined -> ok;
                _ ->
                    ok = gen_event:add_handler(erl_signal_server, erl_signal_handler, [])
            end,
            %% add error handler
	    Type = get_error_logger_type(),
            case error_logger:swap_handler(Type) of
                ok -> {ok, Pid, []};
                Error ->
                    %% Not necessary since the node will crash anyway:
                    exit(Pid, shutdown),
                    Error
            end;
	Error -> Error
    end.

...

get_error_logger_type() ->
    case application:get_env(kernel, error_logger) of
	{ok, tty} -> tty;
	{ok, {file, File}} when is_list(File) -> {logfile, File};
	{ok, false} -> false;
	{ok, silent} -> silent;
	undefined -> tty; % default value
	{ok, Bad} -> exit({bad_config, {kernel, {error_logger, Bad}}})
    end.

 kernel启动的时候,通过读取kernel.app的配置,更换error_logger处理句柄为tty,也只有设置为silent的时候才不会将错误日志输出到控制台

erl -kernel error_logger silent -boot start_sasl -config elog

%% 查看error_logger处理句柄

gen_event:which_handlers(error_logger).
[log_mf_h,error_logger]
 

这个时候,tty句柄就不在了

 3 、成熟的日志系统

ejabberd的日志系统。它包含两个部分:

dynamic_compile.erl   动态编译基础模块

ejabberd_logger_h.erl  这是个gen_event behavior模块,可以定制我们写日志的行为

ejabberd_loglevel.h    这个是ejabberd日志系统的精华,可以在运行时动态调节日志的输出级别。

 

用法很简单:

error_logger:add_report_handler(ejabberd_logger_h, LogPath),

ejabberd_loglevel:set(4) //级别4是info日志

 

这个时候,就可以将日志输出到文档,tty不会再显示日志信息

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值