【erlang】lager源码剖析

        lager是erlang的日志库,源码在:https://github.com/erlang-lager/lager ,支持多个日志接收器,能够通过配置控制大量日志输出时节点的处理,以防止节点宕掉,适合生产环境中使用。参照官方文档对于每个配置参数的解释,能够适应大多数使用情况,但是有可能遇到配置了某些参数却不生效的情况,这时候需要结合源码理解每个参数。

  一、整体框架

    lager主要使用了gen_event,可以有多个回调模块,当调用到gen_event:notify的时候,所有的回调模块都会被调用,整体的架构如下图:

    二、配置

2.1 同步异步

从2.0版开始,gen_event采用混合方法。它轮询自己的邮箱大小,并根据邮箱大小在同步和异步之间切换消息传递。

{ async_threshold_window,5 },

{ async_threshold_window,20 }   

邮箱超过20使用同步,邮箱降低到20-5=15时使用异步

在lager_backend_throttle.erl中,这部分对应的代码:

handle_event({log, _Message},State) ->
    {message_queue_len, Len} = erlang:process_info(self(), message_queue_len),
    case {Len > State#state.hwm, Len < State#state.window_min, State#state.async} of
        {true, _, true} ->
            %% need to flip to sync mode
            ?TOGGLE_SYNC(),
            lager_config:set({State#state.sink, async}, false),
            {ok, State#state{async=false}};
        {_, true, false} ->
            %% need to flip to async mode
            ?TOGGLE_ASYNC(),
            lager_config:set({State#state.sink, async}, true),
            {ok, State#state{async=true}};
        _ ->
            %% nothing needs to change
            {ok, State}
    end;

2.2 限制每秒钟的日志量

{error_logger_hwm,50}

理想中配置了这个参数,就应该把每秒钟日志量限制在50,但是实际使用时发现,这个参数只对当进程crash时引发的错误日志会被限制,而普通的error或者info日志并不能起到限制的作用, 这是因为,我们的error和info日志的handle都是lager_file_backend。所以如果要限制他们的每秒钟日志量,需要配置high_water_mark参数。

{high_water_mark,50}

初始化handle的时候,high_water_mark这个配置的值取出来放到了Shaper的hwm字段中,接下来看当日志到达时,handle检查hwm

 只有这个字段有值得时候,日志才会被限制,通常也和参数flush_queue一起配置。

可以控制每秒钟日志量的配置参考:

{lager_file_backend, [{file, \"error.log\"}, {level, error}, {count, 5}, {size, 10485760},{high_water_mark,50},{flush_queue,true}]},
{lager_file_backend, [{file, \"info.log\"}, {level, info}, {count, 5}, {size, 10485760},{high_water_mark,50},{flush_queue,true}]}

实际测试下来,大多数情况下都能限制在每秒钟只打50条,少数情况下会在50周围浮动。

三、lager.erl中为什么没有info(),error()等接口

    使用的时候都是lager:info()这样去调用lager的接口,但是打开lager.erl却找不到对应的接口实现,这是因为使用了parse transform 得到调用地方的行号,模块名,函数名等信息,在生成目标二进制时,编译器会调用lager_transform:parse_transform/2修改代码的abstract code 然后再进行编译,所以生成的beam文件并不是你代码的beam文件。

文件编译指定了{parse_transform, lager_transform}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值