zoukankan      html  css  js  c++  java
  • erlang 错误日志

    错误日志

    OTP系统已经内置了一个可定制的错误日志模块。我们可以从三种不同的视角来看错误日志。程序员的视角关注代码中要记录一个错误日志的函数调用?配置的视角关注错误日志如何存储以及保存在哪里?报告的视角则关心错误发生之后,如何进行分析。我们将逐条讲述这些内容。

    记录一个错误日志

    在程序员的视角,错误日志的API很简单,下面是这些API的一部分:

    @spec error_logger:error_msg(String) -> ok

    向错误日志发送一个错误消息

    1> error_logger:error_msg("An error has occurred ").

    =ERROR REPORT==== 28-Mar-2007::10:46:28 === An error has occurred

    ok

    @spec error_logger:error_msg(Format, Data) -> ok

    向错误日志发送一个错误消息。它的参数与io:format(Format, Data)函数的参数一样。

    2> error_logger:error_msg("~s, an error has occurred ", ["Joe"]).

    =ERROR REPORT==== 28-Mar-2007::10:47:09 === Joe, an error has occurred

    ok

    @spec error_logger:error_report(Report) -> ok

    向错误日志发送一个标准错误报告。

    @type Report = [{Tag, Data} | term()] | string() | term()]

    @type Tag = term()

    @type Data = term()

    3> error_logger:error_report([{tag1,data1},a_term,{tag2,data}]).

    =ERROR REPORT==== 28-Mar-2007::10:51:51 ===

    tag1: data1

    a_term tag2: data

    需要说明的是,这只是可用错误日志API中的一小部分。详细讨论这些API没啥意思。下面的例子中,我们也只会用到error_msg。完整的细节可以参考手册中error_logger的部分。

    配置错误日志

    可以对错误日志进行多种配置。在Erlangshell中我们可以看到所有的错误信息(如果我们什么都不配,这就是默认的配置)。我们可以把报告给shell中的错误写到一个格式化的文本文件中。此外,我们还能创建一个循环日志。你可以把循环日志想像成一个由错误日志产生的巨大环形缓存区域。新的消息进来时,会把它加到日志的尾部,如果日志被装满了,最早的条目就会被清除。

    循环日志是一个极有用的特性。你可以决定总共有多少个日志文件,以及单个日志文件的大小。系统负责帮你删除旧文件以及创建新文件,以维持整个巨大的环形数据区域。你可以调整日志大小,以用来记录最近几天的操作,这在大多数情况下都是绰绰有余的了。

    标准错误日志

    启动Erlang的时候,我们可以给系统设置一些启动参数:

    $ erl -boot start_clean

    这会创建一个适合程序开发的环境。只会提供错误日志的简单形式(不带boot参数的erl启动命令其效果等同于erl –boot start_clean)。

    $erl –boot start_sasl

    这会创建一个适合产品化系统的环境。SASLSystem Architecture Support Libraries的缩写,它负责错误日志,过载保护等等。

    谁也没法记住日志记录器的所有配置(也没这个必要),所以,最好还是把错误日志文件的配置信息记到一个配置文件中。 下面的小节,我们会考察默认配置下系统中的错误日志是如何工作的。然后会了解四种典型的配置方式下,错误日志不同的工作方式。

    不进行配置的SASL

    这是在SASL下启动,不进行配置的情况:

    $ erl -boot start_sasl

    Erlang (BEAM) emulator version 5.5.3 [async-threads:0] ...

    =PROGRESS REPORT==== 27-Mar-2007::11:49:12 ===

    supervisor: {local,sasl_safe_sup}

    started: [{pid,<0.32.0>},

    {name,alarm_handler},

    {mfa,{alarm_handler,start_link,[]}},

    {restart_type,permanent},

    {shutdown,2000},

    {child_type,worker}]

    ... many lines removed ...

    Eshell V5.5.3 (abort with ^G)

    现在我们调用error_logger的方法来报告错误:

    1> error_logger:error_msg("This is an error ").

    =ERROR REPORT==== 27-Mar-2007::11:53:08 === This is an error

    ok

    注意,错误是在Erlangshell中报告出来的。错误报告取决于错误日志记录器的配置。

    控制记录何种日志

    错误日志记录器会产生几种类型的报告:

    Supervisor报告

    Supervisor启动或者停止被监管的进程时,会产生这个报告(我们在18.5节监管树“第345页”中会讨论它)。

    Progress报告

    每次OTP监管进程启动或者停止的时候会产生这个报告。

    Crash报告

    当被监管的进程退出时,如果它的退出原因不是normal或者shutdown,就会产生这个报告。

    这三种报告是自动产生的,程序员无需关心。除此之外,当程序显式调用error_handler的方法时,也会产生三种日志报告。通过这三种报告,程序可以记录错误,警报以及提示信息。在这里,这三个术语并没有什么特别的语意,仅仅是程序员可以使用的三种标签,用来标明错误日志条目的自然属性(也就是说,想怎么用,随你)。

    在日后对错误日志进行分析的时候,我们可以用这三种标签协助我们来检查问题,过滤日志条目。在对日志进行配置的时候,我们也可以指定,比如,只保存错误,其他的信息不予保存。下面我们就来写一个这样的配置文件。

    elog1.config

    %% no tty

    [{sasl, [

    {sasl_error_logger, false}

    ]}].

    如果用这个配置文件启动系统,只有错误报告会被记录,progress报告之类的全部被忽略掉。而且,所有的错误都报告在shell当中。

    $ erl -boot start_sasl -config elog1

    1> error_logger:error_msg("This is an error ").

    =ERROR REPORT==== 27-Mar-2007::11:53:08 === This is an error

    Ok

    文本文件和shell

    无配置方法:

    erl -boot start_sasl -sasl sasl_error_logger {file,"path/to/logfile.log"} 

    %%有些{}不需转义.

    下一个配置文件,错误信息会同时出现在shell和一个文本文件之中:

    elog2.config

    %% single text file - minimal tty

    [{sasl, [

    %% All reports go to this file

    {sasl_error_logger, {file, "/home/joe/error_logs/THELOG" }}

    ]}].

    我们启动Erlang,生成一些错误信息,然后看看日志文件,以检查这个配置文件的效果。

    $ erl -boot start_sasl -config elog2

    1> error_logger:error_msg("This is an error ").

    =ERROR REPORT==== 27-Mar-2007::11:53:08 === This is an error ok

    我们可以查看/home/joe/error_logs/THELOG文件的内容,应该是这样的:

    =PROGRESS REPORT==== 28-Mar-2007::11:30:55 ===

    supervisor: {local,sasl_safe_sup}

    started: [{pid,<0.34.0>},

    {name,alarm_handler},

    {mfa,{alarm_handler,start_link,[]}},

    {restart_type,permanent},

    {shutdown,2000},

    {child_type,worker}]

    ...

    循环日志和Shell

    这个配置下,日志会在Shell以及一个循环日志中同时输出。这是一个很有用的配置。

    elog3.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 elog3

    1> error_logger:error_msg("This is an error ").

    =ERROR REPORT==== 28-Mar-2007::11:36:19 === This is an error

    False

    当用这个配置运行系统的时候,所有的错误也会输出到这个循环日志中。本章后面的章节,我们会看到从日志中提取错误信息的方法。

    产品化环境

    在产品化环境中,我们只关注错误,而对progressinformation日志不感兴趣。所有我们在配置中让日志记录器仅仅记录错误。以免这些信息淹没在大量的progressinformation日志中。

    elog4.config

    %% rotating log and errors

    [{sasl, [

    %% minimise shell error logging

    {sasl_error_logger, false},

    %% only report errors

    {errlog_type, error},

    %% 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

    {error_logger_mf_maxfiles, 10}

    ]}].

    运行的时候,这个配置与前一个配置的效果看起来很相似,唯一的区别在于,只有错误会被记录到日志中。

    分析错误日志

    读取错误日志是rb模块的职责。它的接口相当简单。

    1> rb:help().

    Report Browser Tool - usage

    ===========================

    rb:start()  - start the rb_server with default options rb:start(Options) - where Options is a list of:

    {start_log, FileName}

    - default: standard_io

    {max, MaxNoOfReports}

    - MaxNoOfReports should be an integer or 'all'

    - default: all

    ...

    ... 此处省略很多行 ...

    ...

    我们启动report browser的时候可以指定它需要读取多少行(这个例子中,是最后的20行)

    2> rb:start([{max,20}]).

    rb: reading report...done.

    3> rb:list().

    No   Type       Process Date  Time

    ==   ====      ======= ====     ====

    11    progress <0.29.0> 2007-03-28 11:34:31

    10    progress <0.29.0> 2007-03-28 11:34:31

    9     progress <0.29.0> 2007-03-28 11:34:31

    8     progress <0.29.0> 2007-03-28 11:34:31

    7     progress <0.22.0> 2007-03-28 11:34:31

    6     progress <0.29.0> 2007-03-28 11:35:53

    5     progress <0.29.0> 2007-03-28 11:35:53

    4     progress <0.29.0> 2007-03-28 11:35:53

    3     progress <0.29.0> 2007-03-28 11:35:53

    2     progress <0.22.0> 2007-03-28 11:35:53

    1     error       <0.23.0> 2007-03-28 11:36:19

    ok

    > rb:show(1).

    ERROR REPORT <0.40.0>   2007-03-28 11:36:19

    ===========================================================

    This is an error ok

    要隔离一个特定的错误,我们可以使用rb:grep(RegExp)命令。它会找出所有匹配这个正则表达式的记录。我这里就不深入分析错误日志的细节问题了,学习它的最好方法是花一点时间,自己来和rb进行一些交互,看看都能做点什么。注意,你根本不需要自己来删日志,循环机制会删除旧的日志。

    如果你想要保留所有的日志,那么你就需要每隔一段特定的时间过来抓取,并自己进行清理。

  • 相关阅读:
    js去重的es6做法和es5做法
    对npm的认识
    pandas_分类与聚合
    pandas_使用透视表与交叉表查看业绩汇总数据
    pandas_使用属性接口实现高级功能
    pandas_一维数组与常用操作
    pandas_DateFrame的创建
    python 连接 mysql 的三种驱动
    Django学习路6_修改数据库为 mysql ,创建mysql及进行迁徙
    Django学习路5_更新和删除数据库表中元素
  • 原文地址:https://www.cnblogs.com/xiao0913/p/3597121.html
Copyright © 2011-2022 走看看