http://blog.sina.com.cn/s/blog_96b8a1540101317g.html

一、基本概念

在Erlang中,通过两个概念管理错误事情:事件管理器(event manager)和事件处理句柄(event handles)。通常各种错误、警告和消息事件都会有Erlang运行时系统发送给事件管理器。在Erlang中,默认的事情管理器为error logger,其进程名注册为error_logger。默认情况下error_logger把这些事件直接输出到控制台上。

在系统启动的一开始,error_logger只有一个简单的事件处理句柄,该处理句柄只是做缓冲和原始格式的打印操作。查看error_logger的源码,可以看到其启动过程如下:

-spec start() -> {'ok', pid()} | {'error', any()}.

start() ->

case gen_event:start({local, error_logger}) of

{ok, Pid} ->

simple_logger(?buffer_size),

{ok, Pid};

Error -> Error

end.

-spec start_link() -> {'ok', pid()} | {'error', any()}.

start_link() ->

case gen_event:start_link({local, error_logger}) of

{ok, Pid} ->

simple_logger(?buffer_size),

{ok, Pid};

Error -> Error

end.

OK,只是简单的注册了一个进程,看看simple_logger的内容:

simple_logger(Buffer_size) when is_integer(Buffer_size) ->

gen_event:add_handler(error_logger, error_logger, Buffer_size).

看来error_logger在一开始的时候除了充当manager,也担当了handler的角色。

在启动的过程中,kernel application使用一个标准的事件处理句柄来代替之前的那个简单版本,这个版本会将输出到控制台的结果做个漂亮的格式化。当然,可以通过kernel的配置选项来修改上述行为,例如将结果输出到文件或者干脆什么都不干(忽略任何event)。口说无凭,还是继续看源码吧:

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

可以看出,如果我们真的希望什么都不做,那么应该传递参数 silent,而不是false,因为false情况下原来的原始处理句柄并没有被移除掉。

打开命令提示符,做个简单的实验(>表示命令提示符):

实验一,定制为false参数:

> erl -kernel error_logger false  //传递false参数

2> error_logger:error_msg("Haha").  // 尝试产生一个error event

ok{error_logger,{{

2010,2> 3,10},{15,9,1}},"Haha",[]}  //这里是结果

实验二,定制为silent参数:

> erl -kernel error_logger silent  //传递silent 参数

1>  error_logger:error_msg("Haha").

ok   // 看到这里只有ok,没有其他任何信息了!

2>

三、SASL

SASL全称System Architecture Support Libraries,提供如下几个服务:

alarm_handler

overload

rb

release_handler

systools

SASL带有error_logger的事件处理句柄用于格式化SASL错误和crash报告,这些句柄如下:

sasl_report_tty_h   sasl_report_file_h   error_logger_mf_h

细节参考OTP文档可知。

SASL的默认event handler会将crash报告、supervisor和进程报告输出到控制台,如果你希望看到这些信息,那么在erlang启动时需要加上指定的参数以启动sasl。

为了方便日志的查看,通常sasl和其他日志是分开输出的,可以在启动erl时使用如下命令行参数:

-sasl sasl_error_logger {file,"/data/ log/sasl.log"}

四、站在巨人的肩膀上

这里并不打算介绍一个gen_event behavior模块的写法,而是想介绍一个非常强大、成熟的一个日志系统: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日志

原理很简单,利用code模块的load_binary来实现动态代码替换,但是确实非常强大,可以在需要的时候打开某些特定级别的日志,在系统负载高的时候或者不需要的时候关闭它。

Erlang中日志管理的更多相关文章

  1. web项目中日志管理工具的使用

    在web项目中,很多时候会用到日志管理工具,常见的日志管理用具有:JDK logging(配置文件:logging.properties) 和log4j(配置文件:log4j.properties) ...

  2. Django中日志管理

    在settings中设置日志的相关信息,然后再逻辑代码区就可以保存相应的信息了 #简单设置: LOGGING = { 'version': 1, 'disable_existing_loggers': ...

  3. SpringBoot | 第二十三章:日志管理之整合篇

    前言 在本系列<第四章:日志管理>中,由于工作中日志这块都是走默认配置,也没有深入了解过,因为部署过程中直接使用了linux中的输出重定向功能,如java -jar xx.jar > ...

  4. 利用log4j+mongodb实现分布式系统中日志统一管理

    背景     在分布式系统当中,我们有各种各样的WebService,这些服务可能分别部署在不同的服务器上,并且有各自的日志输出.为了方便对这些日志进行统一管理和分析.我们可以将日志统一输出到指定的数 ...

  5. 如何在 ETL 项目中统一管理上百个 SSIS 包的日志和包配置框架

    一直准备写这么一篇有关 SSIS 日志系统的文章,但是发现很难一次写的很完整.因为这篇文章的内容可扩展的性太强,每多扩展一部分就意味着需要更多代码,示例和理论支撑.因此,我选择我觉得比较通用的 LOG ...

  6. SQL Server中的事务日志管理(7/9):处理日志过度增长

    当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会 ...

  7. SQL Server中的事务日志管理(9/9):监控事务日志

    当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会 ...

  8. SQL Server中的事务日志管理(5/9):完整恢复模式里的日志管理

    当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会 ...

  9. SQL Server中的事务日志管理(3/9):事务日志,备份与恢复

    当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会 ...

随机推荐

  1. .net core 分布式性能计数器的实现

    1.特别鸣谢张善友老师的指点; 2.分布式性能计数器链接地址:https://mp.weixin.qq.com/s/hPV_bNZD4XmjP0QTE54pWA

  2. 39.Intellij导入子项目时,maven列表子项目灰色不可用---解决方法

    转自:https://blog.csdn.net/jackieriver/article/details/79046326 导入子项目的module时,左侧project目录中有一个module图标右 ...

  3. Android 图片缓存处理

    异步下载 / 本地缓存 异步下载 大家都知道,在Android应用中UI线程5秒没响应的话就会抛出无响应异常,对于远程获取大的资源来说,这种异常还是很容易就会抛出来的,那么怎么避免这种问题的产生.在a ...

  4. 【习题 6-4 UVA-439】Knight Moves

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] bfs模板题 [代码] /* 1.Shoud it use long long ? 2.Have you ever test sev ...

  5. 51Nod——N1118 机器人走方格

    https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1118 基准时间限制:1 秒 空间限制:131072 KB 分值: 0  ...

  6. zabbix自定义监控mysql

    创建用户: use mysql; grant all privileges on *.* to 'zabbix'@'%' identified by 'zabbixpasswd'; grant all ...

  7. vue指令概览

    原文 简书原文:https://www.jianshu.com/p/5fd47b7422fd 大纲 1.什么是vue指令 2.向指令中传入参数 3.指令中带入修饰符 4.指令的缩写 5.常见的vue指 ...

  8. 组件绑定v-model,实现最大化复用

    看优秀的vue项目,对组件的封装做的都非常到位,比如一个按钮都可以实现复用,仔细研究会发现实现基础就是组件直接绑定v-model,来看看按钮: 比如有个点赞按钮,长这样: 当点赞之后变成这样: 相信很 ...

  9. (转)在server 2008R2组策略设置所有域计算机防火墙都处于更关闭状态

    组策略在域控中相当重要,我们可以下放一个组策略去统一管理下面客户端的配置,具体配置如下: 首先点击开始____管理工具____组策略管理 防火墙关闭完之后我们该如何到客户端验证呢? 首先我们需要现在客 ...

  10. 浅谈求lca

    lca即最近公共祖先,求最近公共祖先的方法大概有3种,其实是窝只听说过3种,这3种做法分别是倍增求lca,树剖求lca和tarjan求lca,但是窝只会前2种,所以这里只说前2种算法了. 首先是倍增求 ...