rewrite from lager
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
6.5 KiB

-include("lgCom.hrl").
%% 应用名字
-define(LgAppName, eLog).
%% 错误日志宏定义
-define(ERR(Format), error_logger:error_msg(Format)).
-define(ERR(Format, Args), error_logger:error_msg(Format, Args)).
-define(Print(Args), io:format("IMY************~p~n", [Args])).
%% 额外进程字典key
-define(PdMdKey, pdLgMd).
-define(LgTrackSink, '_trace_sink').
%% 旋转日志超时时间
-define(LgRotateTimeout, 100000).
%% 部分默认配置值
-define(LgDefTracer, lgDefTracer).
-define(LgErrLogSink, errLoggerEvent).
%% lgBkdConsole的选项
-type lgConsoleOpt() ::
{id, atom() | {atom(), atom()}} | %% 接收器 id
{level, lgAtomLevel() | atom()} | %% 接收器 等级级别
{use_stderr, boolean()} | %% 错误输出io
{group_leader, false | pid() | atom()} | %% group_leader
{fmtTer, atom()} | %% 日志格式化的模块名
{fmtCfg, list()}. %% 日志格式化的格式
%% lgBkdFile的选项
-type lgFileOpt() ::
{id, atom()} | %% 接收器 id
{file, binary()} | %% base log file whole log name: logRoot ++ timeMin ++ "_" ++ this name
{level, lgAtomLevel() | atom()} | %% 接收器 等级级别
{size, non_neg_integer()} | %% 单个日志文件最大的字节数 为0则不旋转日志文件
{date, string()} | %% 日志旋转的日期配置
{count, non_neg_integer()} | %% 无用
{rotator, atom()} | %% 日志旋转模块
{hwm, non_neg_integer()} | %% 每一秒能能接收的日志数量 undefined 则不限制每秒接受的日志数量
{flushQueue, boolean()} | %% 对于特定的接收器事件队列刷新,对于接收器 请使用改选项
{flushThr, non_neg_integer()} | %% 如果flush_queue为true,则可以设置消息队列长度阈值,如果超过该阈值处将开始丢弃消息。默认阈值为0,这意味着如果flush_queue为true,则超过高水位标记时将丢弃消息,而不管消息队列的长度如何。:
{syncInt, non_neg_integer()} | %% 日志文件同步间隔
{syncSize, non_neg_integer()} | %% 日志文件同步大小
{syncOn, lgAtomLevel()} | %% 日志文件立即同步的 日志登记级别
{checkInt, non_neg_integer()} | %% 日志文件检查的时间间隔
{fmtTer, atom()} | %% 日志格式化的模块
{fmtCfg, term()}. %% 日志格式化的格式
%% BkdFile选项默认值
-define(LgDefLogLevel, info).
-define(LgDefRotateSize, 10485760). %% 10mb
-define(LgDefRotateDate, <<"$D0">>). %% midnight
-define(LgDefRotateCnt, 5).
-define(LgDefRotateMod, lgRotatorIns).
-define(LgDefSyncLevel, error).
-define(LgDefSyncInt, 1000). %% 单位毫秒
-define(LgDefSyncSize, 1024 * 64). %% 64kb
-define(LgDefCheckInt, 1000). %% 单位毫秒
-define(LgDefCheckHwm, undefined).
-define(LgDefFlushQueue, false).
-define(LgDefFlushThr, 10).
-define(LgDefFmtTer, lgFmtTer).
-define(LgDefFormatterCfg, []).
-define(LgDefLogRoot, <<"./log">>).
%% 默认日志文件选项
-define(LgDefHandler,
[
% {lgBkdConsole, [{level, '>=info'}]},
{lgBkdFile, [{id, info}, {file, <<"info.log">>}, {level, '>= info'}, {size, 10485760}, {date, <<"$D0">>}]},
{lgBkdFile, [{id, error}, {file, <<"error.log">>}, {level, '>= error'}, {size, 10485760}, {date, <<"$D0">>}]}
]).
-record(lgShaper, {
id :: any()
%% 每秒我们尝试传递多少消息
, hwm = undefined :: 'undefined' | pos_integer()
%% 这秒内我们收到了多少条消息
, mps = 0 :: non_neg_integer()
%% 当前秒
, lastTime = lgTime:now() :: erlang:timestamp()
%% 此秒内丢弃的消息数
, dropped = 0 :: non_neg_integer()
%% If true, flush notify messages from msg queue at overload
%% 如果为true,则在过载时刷新来自消息队列的通知消息
, flushQueue = true :: boolean()
, flushThr = 0 :: integer()
%% timer
, timer = make_ref() :: reference()
%% optional filter fun to avoid counting suppressed messages against Hwm totals
%% 可选的过滤器函数,以避免对Hwm总数计算抑制消息
, filter = undefined :: fun() %% fun(_) -> false end :: fun()
}).
-record(lgMsg, {
severity :: lgNumLevel()
, pid :: pid()
, node :: node()
, module :: module()
, function :: atom()
, line :: integer()
, metadata :: [tuple()]
, datetime :: binary()
, timestamp :: non_neg_integer()
, message :: list()
, destinations :: list()
}).
-type lgShaper() :: #lgShaper{}.
-type lgMsg() :: #lgMsg{}.
-type lgAtomLevel() :: none | debug | info | notice | warning | error | critical | alert | emergency.
-type lgNumLevel() :: 0 | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128.
-type lgMaskLevel() :: 0..256.
%% 日志等级列表
-define(LgLevels, [debug, info, notice, warning, error, critical, alert, emergency, none]).
-define(LgShouldLog(Sink, Level), ?eLogCfg:get(Sink) band Level =/= 0).
-define(LgShouldLog(Level), ?eLogCfg:get(?LgDefSink) band Level =/= 0).
-define(LgNotify(Level, Pid, Format, Args),
gen_emm:info_notify(?LgDefSink, {mWriteLog, #lgMsg{severity = Level, pid = Pid, node = node(), module = ?MODULE, function = ?FUNCTION_NAME, line = ?LINE, metadata = [], datetime = lgUtil:msToBinStr(), timestamp = lgTime:nowMs(), message = eFmt:format(Format, Args), destinations = []}})).
%%仅供内部使用仅内部非阻塞日志记录调用,当我们仍在启动大型啤酒时尝试进行日志记录(通常为错误)时,会有一些特殊处理。
-define(INT_LOG(Level, Format, Args),
Self = self(),
%%在生成中执行此操作,这样就不会导致从gen_event处理程序调用gen_event:which_handlers的死锁
spawn(
fun() ->
case catch (gen_emm:which_epm(?LgDefSink)) of
X when X == []; X == {'EXIT', noproc}; X == [lgBkdThrottle] ->
%% there's no handlers yet or eLog isn't running, try again
%% in half a second.
timer:sleep(500),
?LgNotify(Level, Self, Format, Args);
_ ->
case ?LgShouldLog(Level) of
true ->
?LgNotify(Level, Self, Format, Args);
_ ->
ok
end
end
end)).