`
ZacMa
  • 浏览: 38912 次
  • 来自: 深圳
社区版块
存档分类
最新评论

<6>error_logger 使用

阅读更多
erlang中日志管理主要有error_loggger 模块,这个模块在系统启动时候就会启动,不过要自己配置是如何管理,整个管理是通过gen_event来注册事件来管理的
常用的 
erl -kernel error_logger tty
erl -kernel error_logger false
erl -kernel error_loggger silent
erl  -kernel error_logger \{file,\"filename\"\} 
这几种方法,tyy是打印终端,false是默认,也是终端,silent是什么也不做,file是写到日志文件,看代码
start_link() ->
    case gen_event:start_link({local, error_logger}) of
    {ok, Pid} ->
        simple_logger(?buffer_size),
        {ok, Pid};
    Error -> Error
end.
simple_logger(Buffer_size) when is_integer(Buffer_size) ->
gen_event:add_handler(error_logger, error_logger, Buffer_size).
就是将自己error_logger模块设置为handler;

当用户调用函数info_msg/2, error_msg/2 如何呢?
info_msg(Format, Args) ->
     notify({info_msg, group_leader(), {self(), Format, Args}}).
notify(Msg) ->
     gen_event:notify(error_logger, Msg).
handle_event(Event, State) ->
     handle_event2(Event, State).

handle_event2(Event, {1, Lost, Buff}) ->
    display(tag_event(Event)),
    {ok, {1, Lost+1, Buff}};
handle_event2(Event, {N, Lost, Buff}) ->
    Tagged = tag_event(Event),
    display(Tagged),
    {ok, {N-1, Lost, [Tagged|Buff]}};
handle_event2(_, State) ->
    {ok, State}.
最后调用dispaly就是显示了,就是把信息格式化输出
那么是如何将信息输出到文件,或者干脆就不输出呢,


在启动的过程中,kernel application使用一个标准的事件处理句柄来代替之前的那个简单版本,这个版本会将输出到控制台的结果做个漂亮的格式化。当然,可以通过kernel的配置选项来修改上述行为,例如将结果输出到文件或者干脆什么都不干
kernel.erl文件:

start(_, []) ->
    case supervisor:start_link({local, kernel_sup}, kernel, []) of
    {ok, Pid} ->
        Type = get_error_logger_type(),
        error_logger:swap_handler(Type),
        {ok, Pid, []};
    Error -> Error
end.

首先,kernel把自己注册为一个名为kernel_sup的监控树进程,其次立刻就更换了error_logger的处理句柄。go on:

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选项

继续接着上面的代码往下走:

swap_handler(tty) ->
    gen_event:swap_handler(error_logger, {error_logger, swap},
              {error_logger_tty_h, []}),
    simple_logger();
swap_handler({logfile, File}) ->
    gen_event:swap_handler(error_logger, {error_logger, swap},
              {error_logger_file_h, File}),
    simple_logger();
swap_handler(silent) ->
    gen_event:delete_handler(error_logger, error_logger, delete),
    simple_logger();
swap_handler(false) ->
ok. % keep primitive event handler as-is

swap_handler就是替换日志的处理handle
当用户设置了 参数就将 handler替换为error_logger_tty_h或者error_logger_file_h模块来处理
error_logger_tty就是格式化,然后用终端输出
error_logger_file就是文件处理
error_logger_file_h.erl

首先初始化打开文件
%% This one is used when we takeover from the simple error_logger.
init({File, {error_logger, Buf}}) ->
    case init(File, error_logger) of
    {ok, {Fd, File, PrevHandler}} ->
        write_events(Fd, Buf),
        {ok, {Fd, File, PrevHandler}};
    Error ->
        Error
    end;

接下来就是各种处理,以info_msg 为例
handle_event(Event, {Fd, File, PrevHandler}) ->
    write_event(Fd, tag_event(Event)),
    {ok, {Fd, File, PrevHandler}};
write_event(Fd, {Time, {info_msg, _GL, {Pid, Format, Args}}}) ->
    T = write_time(maybe_utc(Time), "INFO REPORT"),
    case catch io_lib:format(add_node(Format,Pid), Args) of
    S when is_list(S) ->
        io:format(Fd, T ++ S, []);
    _ ->
        F = add_node("ERROR: ~p - ~p~n", Pid),
        io:format(Fd, T ++ F, [Format,Args])
    end;
也就是如果你在error_logger注册事件,那么来的event包含的信息格式就是
info_msg, group_leader(), {self(), Format, Args}
需要自己处理,才能够得到合理的格式,例如
error_logger:add_file_handler(file_logger).
file_logger.erl代码如下
-module(file_logger).
-behaviour(gen_event).

-export([init/1, handle_event/2, terminate/2]).

init(File) ->
    {ok, Fd} = file:open(File, write),
    {ok, Fd}.
handle_event(ErrorMsg, Fd) ->
    io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
    {ok, Fd}.
terminate(_Args, Fd) ->
    file:close(Fd)._logger, "mzh").

那么当调用error_logger:info_msg("aaaaa").时候,在文件mzh中就
***Error*** {info_msg,<0.24.0>,{<0.57.0>,"aaaa",[]}}
看来不经过格式化输出的信息很难懂啊

error_logger的信息打印有很多接口,
例如
info_msg
info_report
error_msg
error_report
warn_report 这些,有什么区别呢?以info信息为例
info_msg就是将信息写入文件,info_report呢
info_repot/1也同样写如,
info_report/2是将信息写入自定义的handle里面
info_report(Type, Report) -> ok
Types:
Type = any()
Report = report()
Sends a user defined information report event to the error logger. An event handler to handle the event is supposed to have been added. The event is ignored by the standard event handler.
最后还有warning_report/2要看系统的设置,
用warning_map()获取,也可以在启动时候,用erl +W(i,w)来设置

从error_logger_file_h.erl的write_event可以看出,系统代码,没有处理 type为
info_report, error_report的代码,也就是info_report/2, error_report/2,而
info_report/1,和error_report/1的type会被转化为std_info,照常处理

write_event(Fd, {Time, {info_report, _GL, {Pid, std_info, Rep}}}) ->
    T = write_time(maybe_utc(Time), "INFO REPORT"),
    S = format_report(Rep),
    io:format(Fd, T ++ S ++ add_node("", Pid), []);

如果自己想要记录另一份log,只需要拷贝error_logger_file_h.erl稍作改动,注册自己的handler即可,

erlang的日志系统经常使用rb, 启动时候通过
erl -config log 
也可以两个同时使用,就是记录两处log日志
erl   -boot start_sasl \
      -kernel error_logger \{file,\"mzh3\"\} \
      -config log  
就ok,


部分代码分析来自http://www.qingliangcn.com/2010/03/erlang%E4%B8%AD%E6%97%A5%E5%BF%97%E7%AE%A1%E7%90%86%E4%B8%89%E4%B8%A4%E8%AF%9D/
分享到:
评论

相关推荐

    Log4j入门和实例

    logrj.logger.helloappLogger=WARN&lt;br&gt; 以上代码定义了一个Logger组件,名为helloappLogger,并为它分配了一个日志级别WARN,(一共有5种日志级别:FATAL,ERROR,WARN,INFO,DEBUG)&lt;br&gt; 它的日志级别为WARN,在程序口,它的...

    线程安全日志记录器

    (*Logger Interface*)&lt;br&gt; ILogger=interface&lt;br&gt; ['{E43E419D-26AD-48e6-8097-19622CC2043E}']&lt;br&gt; function WriteLog(&lt;br&gt; FileName : String;&lt;br&gt; LogString : String;&lt;br&gt; CloseFileAfterWrote : BOOL = true&lt;br...

    java应用使用log4j将日志发送到Kafka

    在上面的代码中,我们通过`LogManager.getLogger(Main.class)`获取了一个Logger实例,并使用`info`和`error`方法记录日志。这些日志将按照`log4j2.xml`的配置被发送到Kafka。 最后,确保Kafka服务已经启动并且正确...

    rtl8188eu_sina33m_sc3817在服务器最终验证版本_20170710_1106.7z

    &lt;item&gt;"bt-pan"&lt;/item&gt; &lt;/string-array&gt; 2、干掉BT(特别是rtl8723bs的): R:\wyb\rtl8188eu_sina33m_sc3817\android\device\softwinner\astar-d7\astar_d7.mk PRODUCT_PACKAGES += Launcher3 PRODUCT_...

    ( ap6181_sina33m_sc3817r验证通过_20170710_1608没有外层目录.7z

    &lt;integer name="def_screen_off_timeout"&gt;1800000&lt;/integer&gt; &lt;bool name="def_lockscreen_disabled"&gt;true&lt;/bool&gt; 7、请严重注意,全志在这里埋坑了!(坑爹无敌!) Android里面调入配置文件:nvram.txt,里面...

    监控错误日志并通过rabbitMq发送钉钉通知.docx

    &lt;logger name="com.basis" level="error" additivity="false"&gt; &lt;appender-ref ref="mqAsyncAppender" /&gt; &lt;/logger&gt; ``` 这段配置会将`com.basis`包下所有级别的错误日志发送到RabbitMQ,并通过`mqAsyncAppender`...

    PyPI 官网下载 | sca_logger_python-2.2.2.tar.gz

    3. **使用**:在代码的关键位置,我们可以通过调用日志器的方法(如`info()`、`debug()`、`error()`等)来记录日志信息。 四、高级特性 - **自定义日志格式**:`sca_logger_python`可能支持自定义日志格式,包括...

    NlogTest.zip

    private readonly ILogger&lt;MyClass&gt; _logger = NLog.LogManager.Setup().SetupExtensions(e =&gt; e.AutoLoadAssemblies(false)).CreateLogger&lt;MyClass&gt;(); [TestMethod] public void TestDoSomething_WithError() ...

    logback日志分目录分级别案例

    &lt;fileNamePattern&gt;logs/error.%d{yyyy-MM-dd}.log&lt;/fileNamePattern&gt; &lt;maxHistory&gt;30&lt;/maxHistory&gt; &lt;/rollingPolicy&gt; &lt;encoder&gt; &lt;pattern&gt;%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&lt;/pattern&gt;...

    PyPI 官网下载 | rpa_logger-0.1.1.tar.gz

    要安装和使用`rpa_logger`,开发者需要先解压`rpa_logger-0.1.1.tar.gz`,然后在命令行中运行`python setup.py install`或者利用`pip`的install选项,例如`pip install path/to/rpa_logger-0.1.1.tar.gz`。...

    ap6212a0_bb16v3_sina33验证通过BT的功能_wifi部分有问题_20170626_1148没有外层目录.7z

    &lt;item&gt;"bt-pan"&lt;/item&gt; &lt;/string-array&gt; 3、 R:\wyb\ap6212a0_a33_sc3817r\android\device\softwinner\astar-y3\astar_y3.mk # ap6181/6210/6330 sdio wifi fw and nvram #$(call inherit-product-if-exists, ...

    logger.rar_Logger.py_sunlightek2_日志

    总的来说,"logger.rar_Logger.py_sunlightek2_日志"提供的`logger.py`模块,是为程序开发提供日志记录功能的工具,通过合理使用,可以极大地提高开发和维护的效率。在使用前,需要了解其具体接口和配置方法,以便于...

    PyPI 官网下载 | sca_logger_python-1.4.tar.gz

    `sca_logger_python`可能提供了一套完善的方法,帮助开发者定义不同级别的日志,如CRITICAL、ERROR、WARNING、INFO、DEBUG等,以适应不同的应用场景。 在`sca_logger_python-1.4.tar.gz`压缩包内,通常会包含以下...

    Python库 | spk_logger-0.1.4-py3-none-any.whl

    安装完成后,开发者可以在项目中导入并使用spk_logger提供的功能,例如初始化logger,设置日志级别,添加处理器等。 总结来说,spk_logger-0.1.4-py3-none-any.whl是一个针对Python 3的后端开发日志库,旨在帮助...

    Python库 | melange_logger-0.0.2.tar.gz

    为了使用这个库,开发者首先需要解压`melange_logger-0.0.2.tar.gz`,然后在命令行中运行`pip install .`(如果当前目录是解压后的目录)或者`pip install path/to/melange_logger-0.0.2`(如果不在当前目录)。...

    Python库 | es_logger-2.68.tar.gz

    6. **批量上传**:为了提高效率,`es_logger`可能采用批量上传的方式,将多条日志一次性发送到Elasticsearch,降低网络通信开销。 7. **性能优化**:库可能经过优化,减少了不必要的计算和内存消耗,确保在高负载下...

    Python库 | algorithm_logger-0.0.1-py2.py3-none-any.whl

    总的来说,"algorithm_logger"是一个面向算法开发的日志管理工具,它的`whl`分发包形式使得安装和使用变得简单。无论你是算法工程师还是数据科学家,这个库都值得你去探索和利用,以提升你的工作效率和代码质量。

    log4j配置发送邮件案例

    &lt;pattern&gt;%d{yyyy-MM-dd HH:mm:ss} [%t] %-5level %logger{36} - %msg%n&lt;/pattern&gt; &lt;/layout&gt; &lt;/SMTP&gt; &lt;/appenders&gt; &lt;loggers&gt; &lt;root level="error"&gt; &lt;appender-ref ref="SmtpAppender" /&gt; &lt;/root&gt; &lt;/...

    Python库 | pipeline_logger-1.0.1-py3-none-any.whl

    使用"pipeline_logger"时,应遵循一些最佳实践,如设置合适的日志级别,避免过度记录导致性能影响;在关键代码段使用上下文管理器,确保日志正确关闭;以及合理配置日志处理器,确保日志数据的安全存储和备份。 ...

Global site tag (gtag.js) - Google Analytics