diff --git a/README.md b/README.md index cb6e636..fc06f61 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,7 @@ Examples: 错误记录器集成 ------------------------ error_logger贮藏啤酒还提供了一个处理程序模块,该模块将传统的erlang错误消息转换为更友好的格式,并将其发送到贮藏啤酒中,以像常规贮藏啤酒日志调用一样对待。 -要禁用此功能,请将更大的应用程序变量设置error_logger_redirect为false。您也可以通过设置变量OTP和牛仔消息禁用重新格式化 error_logger_format_raw 为 true。 +要禁用此功能,请将更大的应用程序变量设置error_logger_redirect为false。您也可以通过设置变量OTP和牛仔消息禁用重新格式化 errLoggerFormatRaw 为 true。 如果您将自己的处理程序安装到中error_logger,则可以通过使用error_logger_whitelist环境变量和允许的处理程序列表来告诉lager使其不被处理。 @@ -224,25 +224,25 @@ will send all `error_logger` messages to `error_logger.log` file. 超过高水位标记时,可以将啤酒配置为刷新消息队列中的所有事件通知。这可能会对同一事件管理器(例如中的error_logger)中的其他处理程序产生意想不到的后果,因为它们所依赖的事件可能会被错误地丢弃。默认情况下,此行为已启用,但可以通过以下方式进行控制error_logger: ```erlang -{error_logger_flush_queue, true | false} +{errLoggerFlushQueue, true | false} ``` or for a specific sink, using the option: ```erlang -{flush_queue, true | false} +{flushQueue, true | false} ``` 如果flush_queue为true,则可以设置消息队列长度阈值,在该阈值处将开始丢弃消息。默认阈值为0,这意味着如果flush_queue为true,则超过高水位标记时将丢弃消息,而不管消息队列的长度如何。用于控制阈值的选项是error_logger: ```erlang -{error_logger_flush_threshold, 1000} +{errLoggerFlushThreshold, 1000} ``` and for sinks: ```erlang -{flush_threshold, 1000} +{flushThreshold, 1000} ``` ### 接收器(Sink) Killer diff --git a/eRum.sample.config b/eRum.sample.config index 4860621..0346d06 100644 --- a/eRum.sample.config +++ b/eRum.sample.config @@ -64,18 +64,18 @@ {errLoggerHwm, 50}, %% errLogger group leader策略 handle | ignore | mirror {errLoggerGroupLeaderStrategy, handle}, - {error_logger_format_raw, 1111}, + {errLoggerFormatRaw, false}, %% 对于特定的接收器事件队列刷新,请使用改选项 - {flush_queue, true}, + {flushQueue, true}, %% 对于接收器 如果flush_queue为true,则可以设置消息队列长度阈值,在该阈值处将开始丢弃消息。默认阈值为0, %% 这意味着如果flush_queue为true,则超过高水位标记时将丢弃消息,而不管消息队列的长度如何。: - {flush_threshold, 1000}, + {flushThreshold, 1000}, %% 超过高水位标记时,可以将啤酒配置为刷新消息队列中的所有事件通知 - {error_logger_flush_queue, true}, + {errLoggerFlushQueue, true}, %% 如果flush_queue为true,则可以设置消息队列长度阈值,在该阈值处将开始丢弃消息。默认阈值为0,这意味着如果flush_queue为true, %% 则超过高水位标记时将丢弃消息,而不管消息队列的长度如何。用于控制阈值的选项是error_logger: - {error_logger_flush_threshold, 20}, + {errLoggerFlushThreshold, 20}, %% ********************************************** killer相关 **************************************************** %% 如果接收器的邮箱大小超过1000条消息,请杀死整个接收器并在5000毫秒后重新加载它。如果需要,此行为也可以安装到其他水槽中。 diff --git a/include/eRum.hrl b/include/eRum.hrl index 32237fd..f29dfe6 100644 --- a/include/eRum.hrl +++ b/include/eRum.hrl @@ -155,7 +155,7 @@ %% 这秒内我们收到了多少条消息 , mps = 0 :: non_neg_integer() %% 当前秒 - , lastTime = os:timestamp() :: erlang:timestamp() + , lastTime = rumTime:now() :: erlang:timestamp() %% 此秒内丢弃的消息数 , dropped = 0 :: non_neg_integer() %% If true, flush notify messages from msg queue at overload diff --git a/src/backend/rumBkdFile.erl b/src/backend/rumBkdFile.erl index 2aa4880..ac46004 100644 --- a/src/backend/rumBkdFile.erl +++ b/src/backend/rumBkdFile.erl @@ -79,8 +79,8 @@ init(Opts) -> Count = rumUtil:get_opt(count, Opts, ?RumDefRotateCnt), Rotator = rumUtil:get_opt(rotator, Opts, ?RumDefRotateMod), HighWaterMark = rumUtil:get_opt(high_water_mark, Opts, ?RumDefCheckHWM), - Flush = rumUtil:get_opt(flush_queue, Opts, ?RumDefFlushQueue), - FlushThr = rumUtil:get_opt(flush_threshold, Opts, ?RumDefFlushThreshold), + Flush = rumUtil:get_opt(flushQueue, Opts, ?RumDefFlushQueue), + FlushThr = rumUtil:get_opt(flushThreshold, Opts, ?RumDefFlushThreshold), SyncInterval = rumUtil:get_opt(sync_interval, Opts, ?RumDefSyncInterval), CfgCheckInterval = rumUtil:get_opt(check_interval, Opts, ?RumDefCheckInterval), SyncSize = rumUtil:get_opt(sync_size, Opts, ?RumDefSyncSize), @@ -174,7 +174,7 @@ handleInfo({mRotate, File}, #state{fileName = File, count = Count, date = Date, handleInfo({mShaperExpired, Name}, #state{shaper = Shaper, fileName = Name, formatter = Formatter, formatterConfig = FormatConfig} = State) -> case Shaper#rumShaper.dropped of 0 -> - ok; + ignore; Dropped -> Report = eFmt:format(<<"rumBkdFile dropped ~p messages in the last second that exceeded the limit of ~p messages/sec">>, [Dropped, Shaper#rumShaper.hwm]), ReportMsg = rumMsg:new(Report, warning, [], []), @@ -858,7 +858,7 @@ filesystem_test_() -> {ok, TestDir} = rumUtil:get_test_dir(), TestLog = filename:join(TestDir, "test.log"), gen_event:add_handler(rumEvent, lager_file_backend, [{file, TestLog}, {level, info}, - {high_water_mark, 5}, {flush_queue, false}, {sync_on, "=warning"}]), + {high_water_mark, 5}, {flushQueue, false}, {sync_on, "=warning"}]), {_, _, MS} = os:timestamp(), % start close to the beginning of a new second ?assertEqual(ok, timer:sleep((1000000 - MS) div 1000 + 1)), diff --git a/src/errLogger/rumErrLoggerH.erl b/src/errLogger/rumErrLoggerH.erl index a106c63..6bb8901 100644 --- a/src/errLogger/rumErrLoggerH.erl +++ b/src/errLogger/rumErrLoggerH.erl @@ -1,21 +1,27 @@ -%% @doc A error_logger backend for redirecting events into lager. -%% Error messages and crash logs are also optionally written to a crash log. - -%% @see lager_crash_log - -%% @private - -module(rumErrLoggerH). +%% 一个error_logger后端,用于将事件重定向到eRum。 +%% 错误消息和崩溃日志也可以选择写入崩溃日志。 @see lager_crash_log + -include("eRum.hrl"). -behaviour(gen_event). --export([set_high_water/1]). --export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, - code_change/3]). - --export([format_reason/1, format_mfa/1, format_args/3]). +-export([ + setHighWater/1 + , format_reason/1 + , format_mfa/1 + , format_args/3 +]). + +-export([ + init/1 + , handle_call/2 + , handle_event/2 + , handle_info/2 + , terminate/2, + code_change/3 +]). -record(state, { sink :: atom(), @@ -50,34 +56,36 @@ gen_srv:send(rumCrashLog, {mWriteLog, Event})). -endif. -set_high_water(N) -> - gen_event:call(error_logger, ?MODULE, {set_high_water, N}, infinity). +setHighWater(N) -> + gen_event:call(error_logger, ?MODULE, {mSetHighWater, N}, infinity). -spec init(any()) -> {ok, #state{}}. init([HighWaterMark, GlStrategy]) -> - Flush = application:get_env(lager, error_logger_flush_queue, true), - FlushThr = application:get_env(lager, error_logger_flush_threshold, 0), - Shaper = #rumShaper{hwm = HighWaterMark, flushQueue = Flush, flushThreshold = FlushThr, filter = shaper_fun(), id = ?MODULE}, - Raw = application:get_env(lager, error_logger_format_raw, false), - Sink = configured_sink(), + Flush = rumUtil:get_env(errLoggerFlushQueue, true), + FlushThr = rumUtil:get_env(errLoggerFlushThreshold, 0), + Shaper = #rumShaper{hwm = HighWaterMark, flushQueue = Flush, flushThreshold = FlushThr, filter = shaperFun(), id = ?MODULE}, + Raw = rumUtil:get_env(errLoggerFormatRaw, false), + Sink = configSink(), {ok, #state{sink = Sink, shaper = Shaper, groupleader_strategy = GlStrategy, raw = Raw}}. -handle_call({set_high_water, N}, #state{shaper = Shaper} = State) -> +handle_call({mSetHighWater, N}, #state{shaper = Shaper} = State) -> NewShaper = Shaper#rumShaper{hwm = N}, {ok, ok, State#state{shaper = NewShaper}}; handle_call(_Request, State) -> {ok, unknown_call, State}. -shaper_fun() -> - case {application:get_env(lager, suppress_supervisor_start_stop, false), application:get_env(lager, suppress_application_start_stop, false)} of - {false, false} -> - fun(_) -> false end; - {true, true} -> +shaperFun() -> + SupSS = rumUtil:get_env(suppress_supervisor_start_stop, false), + AppSS = rumUtil:get_env(suppress_application_start_stop, false), + if + SupSS andalso AppSS -> fun suppress_supervisor_start_and_application_start/1; - {false, true} -> + SupSS -> + fun suppress_supervisor_start/1; + AppSS -> fun suppress_application_start/1; - {true, false} -> - fun suppress_supervisor_start/1 + true -> + fun(_) -> false end end. suppress_supervisor_start_and_application_start(E) -> @@ -97,182 +105,194 @@ suppress_supervisor_start(_) -> handle_event(Event, #state{sink = Sink, shaper = Shaper} = State) -> case rumUtil:checkHwm(Shaper, Event) of - {true, 0, NewShaper} -> - eval_gl(Event, State#state{shaper = NewShaper}); - {true, Drop, #rumShaper{hwm = Hwm} = NewShaper} when Drop > 0 -> - ?LOGFMT(Sink, warning, self(), - "lager_error_logger_h dropped ~p messages in the last second that exceeded the limit of ~p messages/sec", - [Drop, Hwm]), - eval_gl(Event, State#state{shaper = NewShaper}); - {false, _, #rumShaper{dropped = D} = NewShaper} -> - {ok, State#state{shaper = NewShaper#rumShaper{dropped = D + 1}}} + {true, _Drop, NewShaper} -> + evalGl(Event, State#state{shaper = NewShaper}); + {drop, Drop, NewShaper} -> + case Drop =< 0 of + true -> + {ok, State#state{shaper = NewShaper}}; + _ -> + ?LOGFMT(Sink, warning, self(), "lager_error_logger_h dropped ~p messages in the last second that exceeded the limit of ~p messages/sec", [Drop, NewShaper#rumShaper.hwm]), + evalGl(Event, State#state{shaper = NewShaper}) + end; + {false, _, NewShaper} -> + {ok, State#state{shaper = NewShaper}} end. handle_info({mShaperExpired, ?MODULE}, #state{sink = Sink, shaper = Shaper} = State) -> case Shaper#rumShaper.dropped of 0 -> - ok; + ignore; Dropped -> - ?LOGFMT(Sink, warning, self(), - "lager_error_logger_h dropped ~p messages in the last second that exceeded the limit of ~p messages/sec", - [Dropped, Shaper#rumShaper.hwm]) + ?LOGFMT(Sink, warning, self(), "lager_error_logger_h dropped ~p messages in the last second that exceeded the limit of ~p messages/sec", [Dropped, Shaper#rumShaper.hwm]) end, - {ok, State#state{shaper = Shaper#rumShaper{dropped = 0, mps = 0, lastTime = os:timestamp()}}}; + {ok, State#state{shaper = Shaper#rumShaper{dropped = 0, mps = 0, lastTime = rumTime:now()}}}; handle_info(_Info, State) -> {ok, State}. terminate(_Reason, _State) -> ok. - code_change(_OldVsn, {state, Shaper, GLStrategy}, _Extra) -> - Raw = application:get_env(lager, error_logger_format_raw, false), + Raw = rumUtil:get_env(errLoggerFormatRaw, false), {ok, #state{ - sink = configured_sink(), + sink = configSink(), shaper = Shaper, groupleader_strategy = GLStrategy, raw = Raw }}; code_change(_OldVsn, {state, Sink, Shaper, GLS}, _Extra) -> - Raw = application:get_env(lager, error_logger_format_raw, false), + Raw = rumUtil:get_env(errLoggerFormatRaw, false), {ok, #state{sink = Sink, shaper = Shaper, groupleader_strategy = GLS, raw = Raw}}; code_change(_OldVsn, State, _Extra) -> {ok, State}. -%% internal functions - -configured_sink() -> - case proplists:get_value(?RumErrLogSink, application:get_env(lager, extraSinks, [])) of +configSink() -> + case rumUtil:get_opt(?RumErrLogSink, rumUtil:get_env(extraSinks, []), undefined) of undefined -> ?RumDefSink; _ -> ?RumErrLogSink end. -eval_gl(Event, #state{groupleader_strategy = GlStrategy0} = State) when is_pid(element(2, Event)) -> - case element(2, Event) of - GL when node(GL) =/= node(), GlStrategy0 =:= ignore -> - gen_event:notify({error_logger, node(GL)}, Event), - {ok, State}; - GL when node(GL) =/= node(), GlStrategy0 =:= mirror -> - gen_event:notify({error_logger, node(GL)}, Event), - log_event(Event, State); +evalGl(Event, #state{groupleader_strategy = GlStrategy0} = State) -> + GL = element(2, Event), + case is_pid(GL) andalso node(GL) =/= node() of + true -> + case GlStrategy0 of + ignore -> + gen_event:notify({error_logger, node(GL)}, Event), + {ok, State}; + mirror -> + gen_event:notify({error_logger, node(GL)}, Event), + logEvent(Event, State); + _ -> + logEvent(Event, State) + end; _ -> - log_event(Event, State) - end; -eval_gl(Event, State) -> - log_event(Event, State). + logEvent(Event, State) + end. -log_event(Event, #state{sink = Sink} = State) -> +logEvent(Event, #state{sink = Sink, raw = FormatRaw} = State) -> DidLog = case Event of {error, _GL, {Pid, Fmt, Args}} -> - FormatRaw = State#state.raw, - case {FormatRaw, Fmt} of - {false, "** Generic server " ++ _} -> - %% gen_server terminate - {Reason, Name} = case Args of - [N, _Msg, _State, R] -> - {R, N}; - [N, _Msg, _State, R, _Client] -> - %% OTP 20 crash reports where the client pid is dead don't include the stacktrace - {R, N}; - [N, _Msg, _State, R, _Client, _Stacktrace] -> - %% OTP 20 crash reports contain the pid of the client and stacktrace - %% TODO do something with them - {R, N} - end, - ?CRASH_LOG(Event), - {Md, Formatted} = format_reason_md(Reason), - ?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "gen_server ~w terminated with reason: ~s", - [Name, Formatted]); - {false, "** State machine " ++ _} -> - %% Check if the terminated process is gen_fsm or gen_statem - %% since they generate the same exit message - {Type, Name, StateName, Reason} = - case Args of - [TName, _Msg, TStateName, _StateData, TReason] -> - {gen_fsm, TName, TStateName, TReason}; - %% Handle changed logging in gen_fsm stdlib-3.9 (TPid, ClientArgs) - [TName, _Msg, TPid, TStateName, _StateData, TReason | _ClientArgs] when is_pid(TPid), is_atom(TStateName) -> - {gen_fsm, TName, TStateName, TReason}; - %% Handle changed logging in gen_statem stdlib-3.9 (ClientArgs) - [TName, _Msg, {TStateName, _StateData}, _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] -> - {gen_statem, TName, TStateName, {TReason, Stacktrace}}; - %% Handle changed logging in gen_statem stdlib-3.9 (ClientArgs) - [TName, {TStateName, _StateData}, _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] -> - {gen_statem, TName, TStateName, {TReason, Stacktrace}}; - [TName, _Msg, [{TStateName, _StateData}], _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] -> - %% sometimes gen_statem wraps its statename/data in a list for some reason??? - {gen_statem, TName, TStateName, {TReason, Stacktrace}} - end, - {Md, Formatted} = format_reason_md(Reason), - ?CRASH_LOG(Event), - ?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "~s ~w in state ~w terminated with reason: ~s", - [Type, Name, StateName, Formatted]); - {false, "** gen_event handler" ++ _} -> - %% gen_event handler terminate - [ID, Name, _Msg, _State, Reason] = Args, - {Md, Formatted} = format_reason_md(Reason), - ?CRASH_LOG(Event), - ?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "gen_event ~w installed in ~w terminated with reason: ~s", - [ID, Name, Formatted]); - {false, "** Cowboy handler" ++ _} -> - %% Cowboy HTTP server error - ?CRASH_LOG(Event), - case Args of - [Module, Function, Arity, _Request, _State] -> - %% we only get the 5-element list when its a non-exported function - ?LOGFMT(Sink, error, Pid, - "Cowboy handler ~p terminated with reason: call to undefined function ~p:~p/~p", - [Module, Module, Function, Arity]); - [Module, Function, Arity, _Class, Reason | Tail] -> - %% any other cowboy error_format list *always* ends with the stacktrace - StackTrace = lists:last(Tail), - {Md, Formatted} = format_reason_md({Reason, StackTrace}), - ?LOGFMT(Sink, error, [{pid, Pid} | Md], - "Cowboy handler ~p terminated in ~p:~p/~p with reason: ~s", - [Module, Module, Function, Arity, Formatted]) - end; - {false, "Ranch listener " ++ _} -> - %% Ranch errors - ?CRASH_LOG(Event), - case Args of - %% Error logged by cowboy, which starts as ranch error - [Ref, ConnectionPid, StreamID, RequestPid, Reason, StackTrace] -> - {Md, Formatted} = format_reason_md({Reason, StackTrace}), - ?LOGFMT(Sink, error, [{pid, RequestPid} | Md], - "Cowboy stream ~p with ranch listener ~p and connection process ~p " - "had its request process exit with reason: ~s", - [StreamID, Ref, ConnectionPid, Formatted]); - [Ref, _Protocol, Worker, {[{reason, Reason}, {mfa, {Module, Function, Arity}}, {stacktrace, StackTrace} | _], _}] -> - {Md, Formatted} = format_reason_md({Reason, StackTrace}), - ?LOGFMT(Sink, error, [{pid, Worker} | Md], - "Ranch listener ~p terminated in ~p:~p/~p with reason: ~s", - [Ref, Module, Function, Arity, Formatted]); - [Ref, _Protocol, Worker, Reason] -> + case FormatRaw of + false -> + case Fmt of + "** Generic server " ++ _ -> + %% gen_server terminate + {Reason, Name} = + case Args of + [N, _Msg, _State, R] -> + {R, N}; + [N, _Msg, _State, R, _Client] -> + %% OTP 20 crash reports where the client pid is dead don't include the stacktrace + {R, N}; + [N, _Msg, _State, R, _Client, _Stacktrace] -> + %% OTP 20 crash reports contain the pid of the client and stacktrace + %% TODO do something with them + {R, N} + end, + ?CRASH_LOG(Event), + {Md, Formatted} = format_reason_md(Reason), + ?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "gen_server ~w terminated with reason: ~s", [Name, Formatted]); + "** gen_ipc State machine " ++ _ -> + %% gen_server terminate + {Reason, Name} = + case Args of + [N, _Msg, _State, R] -> + {R, N}; + [N, _Msg, _State, R, _Client] -> + %% OTP 20 crash reports where the client pid is dead don't include the stacktrace + {R, N}; + [N, _Msg, _State, R, _Client, _Stacktrace] -> + %% OTP 20 crash reports contain the pid of the client and stacktrace + %% TODO do something with them + {R, N} + end, + ?CRASH_LOG(Event), + {Md, Formatted} = format_reason_md(Reason), + ?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "gen_ipc ~w terminated with reason: ~s", [Name, Formatted]); + "** State machine " ++ _ -> + %% Check if the terminated process is gen_fsm or gen_statem + %% since they generate the same exit message + {Type, Name, StateName, Reason} = + case Args of + [TName, _Msg, TStateName, _StateData, TReason] -> + {gen_fsm, TName, TStateName, TReason}; + %% Handle changed logging in gen_fsm stdlib-3.9 (TPid, ClientArgs) + [TName, _Msg, TPid, TStateName, _StateData, TReason | _ClientArgs] when is_pid(TPid), is_atom(TStateName) -> + {gen_fsm, TName, TStateName, TReason}; + %% Handle changed logging in gen_statem stdlib-3.9 (ClientArgs) + [TName, _Msg, {TStateName, _StateData}, _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] -> + {gen_statem, TName, TStateName, {TReason, Stacktrace}}; + %% Handle changed logging in gen_statem stdlib-3.9 (ClientArgs) + [TName, {TStateName, _StateData}, _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] -> + {gen_statem, TName, TStateName, {TReason, Stacktrace}}; + [TName, _Msg, [{TStateName, _StateData}], _ExitType, TReason, _CallbackMode, Stacktrace | _ClientArgs] -> + %% sometimes gen_statem wraps its statename/data in a list for some reason??? + {gen_statem, TName, TStateName, {TReason, Stacktrace}} + end, + {Md, Formatted} = format_reason_md(Reason), + ?CRASH_LOG(Event), + ?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "~s ~w in state ~w terminated with reason: ~s", [Type, Name, StateName, Formatted]); + "** gen_event handler" ++ _ -> + %% gen_event handler terminate + [ID, Name, _Msg, _State, Reason] = Args, {Md, Formatted} = format_reason_md(Reason), - ?LOGFMT(Sink, error, [{pid, Worker} | Md], - "Ranch listener ~p terminated with reason: ~s", - [Ref, Formatted]); - [Ref, Protocol, Ret] -> - %% ranch_conns_sup.erl module line 119-123 has three parameters error msg, log it. - {Md, Formatted} = format_reason_md(Ret), - ?LOGFMT(Sink, error, [{pid, Protocol} | Md], - "Ranch listener ~p terminated with result:~s", - [Ref, Formatted]) + ?CRASH_LOG(Event), + ?LOGFMT(Sink, error, [{pid, Pid}, {name, Name} | Md], "gen_event ~w installed in ~w terminated with reason: ~s", [ID, Name, Formatted]); + "** Cowboy handler" ++ _ -> + %% Cowboy HTTP server error + ?CRASH_LOG(Event), + case Args of + [Module, Function, Arity, _Request, _State] -> + %% we only get the 5-element list when its a non-exported function + ?LOGFMT(Sink, error, Pid, + "Cowboy handler ~p terminated with reason: call to undefined function ~p:~p/~p", + [Module, Module, Function, Arity]); + [Module, Function, Arity, _Class, Reason | Tail] -> + %% any other cowboy error_format list *always* ends with the stacktrace + StackTrace = lists:last(Tail), + {Md, Formatted} = format_reason_md({Reason, StackTrace}), + ?LOGFMT(Sink, error, [{pid, Pid} | Md], + "Cowboy handler ~p terminated in ~p:~p/~p with reason: ~s", [Module, Module, Function, Arity, Formatted]) + end; + "Ranch listener " ++ _ -> + %% Ranch errors + ?CRASH_LOG(Event), + case Args of + %% Error logged by cowboy, which starts as ranch error + [Ref, ConnectionPid, StreamID, RequestPid, Reason, StackTrace] -> + {Md, Formatted} = format_reason_md({Reason, StackTrace}), + ?LOGFMT(Sink, error, [{pid, RequestPid} | Md], + "Cowboy stream ~p with ranch listener ~p and connection process ~p " + "had its request process exit with reason: ~s", [StreamID, Ref, ConnectionPid, Formatted]); + [Ref, _Protocol, Worker, {[{reason, Reason}, {mfa, {Module, Function, Arity}}, {stacktrace, StackTrace} | _], _}] -> + {Md, Formatted} = format_reason_md({Reason, StackTrace}), + ?LOGFMT(Sink, error, [{pid, Worker} | Md], "Ranch listener ~p terminated in ~p:~p/~p with reason: ~s", [Ref, Module, Function, Arity, Formatted]); + [Ref, _Protocol, Worker, Reason] -> + {Md, Formatted} = format_reason_md(Reason), + ?LOGFMT(Sink, error, [{pid, Worker} | Md], "Ranch listener ~p terminated with reason: ~s", [Ref, Formatted]); + [Ref, Protocol, Ret] -> + %% ranch_conns_sup.erl module line 119-123 has three parameters error msg, log it. + {Md, Formatted} = format_reason_md(Ret), + ?LOGFMT(Sink, error, [{pid, Protocol} | Md], "Ranch listener ~p terminated with result:~s", [Ref, Formatted]) + end; + "webmachine error" ++ _ -> + %% Webmachine HTTP server error + ?CRASH_LOG(Event), + [Path, Error] = Args, + %% webmachine likes to mangle the stack, for some reason + StackTrace = + case Error of + {error, {error, Reason, Stack}} -> + {Reason, Stack}; + _ -> + Error + end, + {Md, Formatted} = format_reason_md(StackTrace), + ?LOGFMT(Sink, error, [{pid, Pid} | Md], "Webmachine error at path ~p : ~s", [Path, Formatted]) end; - {false, "webmachine error" ++ _} -> - %% Webmachine HTTP server error - ?CRASH_LOG(Event), - [Path, Error] = Args, - %% webmachine likes to mangle the stack, for some reason - StackTrace = case Error of - {error, {error, Reason, Stack}} -> - {Reason, Stack}; - _ -> - Error - end, - {Md, Formatted} = format_reason_md(StackTrace), - ?LOGFMT(Sink, error, [{pid, Pid} | Md], "Webmachine error at path ~p : ~s", [Path, Formatted]); _ -> ?CRASH_LOG(Event), ?LOGFMT(Sink, error, Pid, Fmt, Args) @@ -306,7 +326,7 @@ log_event(Event, #state{sink = Sink} = State) -> Details = lists:sort(D), case Details of [{application, App}, {exited, Reason}, {type, _Type}] -> - case application:get_env(lager, suppress_application_start_stop, false) of + case rumUtil:get_env(suppress_application_start_stop, false) of true when Reason == stopped -> no_log; _ -> @@ -323,7 +343,7 @@ log_event(Event, #state{sink = Sink} = State) -> Details = lists:sort(D), case Details of [{application, App}, {started_at, Node}] -> - case application:get_env(lager, suppress_application_start_stop, false) of + case rumUtil:get_env(suppress_application_start_stop, false) of true -> no_log; _ -> @@ -331,7 +351,7 @@ log_event(Event, #state{sink = Sink} = State) -> [App, Node]) end; [{started, Started}, {supervisor, Name}] -> - case application:get_env(lager, suppress_supervisor_start_stop, false) of + case rumUtil:get_env(suppress_supervisor_start_stop, false) of true -> no_log; _ -> @@ -351,12 +371,7 @@ log_event(Event, #state{sink = Sink} = State) -> {ok, State}; no_log -> Shaper = State#state.shaper, - {ok, State#state{ - shaper = Shaper#rumShaper{ - mps = Shaper#rumShaper.mps - 1 - } - } - } + {ok, State#state{shaper = Shaper#rumShaper{mps = Shaper#rumShaper.mps - 1}}} end. format_crash_report(Report, Neighbours) -> @@ -379,12 +394,8 @@ format_crash_report(Report, Neighbours) -> {Class, Reason, Trace} = get_value(error_info, Report), {Md, ReasonStr} = format_reason_md({Reason, Trace}), - Type = case Class of - exit -> "exited"; - _ -> "crashed" - end, - {Md0 ++ Md, io_lib:format("Process ~w with ~w neighbours ~s with reason: ~s", - [Name, length(Neighbours), Type, ReasonStr])}. + Type = ?IIF(Class == exit, <<"exited">>, <<"crashed">>), + {Md0 ++ Md, eFmt:formatBin("Process ~w with ~w neighbours ~s with reason: ~s", [Name, length(Neighbours), Type, ReasonStr])}. format_offender(Off) -> case get_value(mfargs, Off) of @@ -416,80 +427,64 @@ format_reason(Reason) -> format_reason_md({'function not exported', [{M, F, A}, MFA | _]}) -> {Md, Formatted} = format_mfa_md(MFA), {_, Formatted2} = format_mfa_md({M, F, length(A)}), - {[{reason, 'function not exported'} | Md], - ["call to undefined function ", Formatted2, - " from ", Formatted]}; + {[{reason, 'function not exported'} | Md], ["call to undefined function ", Formatted2, " from ", Formatted]}; format_reason_md({'function not exported', [{M, F, A, _Props}, MFA | _]}) -> %% R15 line numbers {Md, Formatted} = format_mfa_md(MFA), {_, Formatted2} = format_mfa_md({M, F, length(A)}), - {[{reason, 'function not exported'} | Md], - ["call to undefined function ", Formatted2, - " from ", Formatted]}; + {[{reason, 'function not exported'} | Md], ["call to undefined function ", Formatted2, " from ", Formatted]}; format_reason_md({undef, [MFA | _]}) -> {Md, Formatted} = format_mfa_md(MFA), - {[{reason, undef} | Md], - ["call to undefined function ", Formatted]}; + {[{reason, undef} | Md], ["call to undefined function ", Formatted]}; format_reason_md({bad_return, {_MFA, {'EXIT', Reason}}}) -> format_reason_md(Reason); format_reason_md({bad_return, {MFA, Val}}) -> {Md, Formatted} = format_mfa_md(MFA), - {[{reason, bad_return} | Md], - ["bad return value ", print_val(Val), " from ", Formatted]}; + {[{reason, bad_return} | Md], ["bad return value ", print_val(Val), " from ", Formatted]}; format_reason_md({bad_return_value, Val}) -> - {[{reason, bad_return}], - ["bad return value: ", print_val(Val)]}; + {[{reason, bad_return}], ["bad return value: ", print_val(Val)]}; format_reason_md({{bad_return_value, Val}, MFA}) -> {Md, Formatted} = format_mfa_md(MFA), - {[{reason, bad_return_value} | Md], - ["bad return value: ", print_val(Val), " in ", Formatted]}; + {[{reason, bad_return_value} | Md], ["bad return value: ", print_val(Val), " in ", Formatted]}; format_reason_md({{badrecord, Record}, [MFA | _]}) -> {Md, Formatted} = format_mfa_md(MFA), - {[{reason, badrecord} | Md], - ["bad record ", print_val(Record), " in ", Formatted]}; + {[{reason, badrecord} | Md], ["bad record ", print_val(Record), " in ", Formatted]}; format_reason_md({{case_clause, Val}, [MFA | _]}) -> {Md, Formatted} = format_mfa_md(MFA), - {[{reason, case_clause} | Md], - ["no case clause matching ", print_val(Val), " in ", Formatted]}; + {[{reason, case_clause} | Md], ["no case clause matching ", print_val(Val), " in ", Formatted]}; format_reason_md({function_clause, [MFA | _]}) -> {Md, Formatted} = format_mfa_md(MFA), - {[{reason, function_clause} | Md], - ["no function clause matching ", Formatted]}; + {[{reason, function_clause} | Md], ["no function clause matching ", Formatted]}; format_reason_md({if_clause, [MFA | _]}) -> {Md, Formatted} = format_mfa_md(MFA), - {[{reason, if_clause} | Md], - ["no true branch found while evaluating if expression in ", Formatted]}; + {[{reason, if_clause} | Md], ["no true branch found while evaluating if expression in ", Formatted]}; format_reason_md({{try_clause, Val}, [MFA | _]}) -> {Md, Formatted} = format_mfa_md(MFA), - {[{reason, try_clause} | Md], - ["no try clause matching ", print_val(Val), " in ", Formatted]}; + {[{reason, try_clause} | Md], ["no try clause matching ", print_val(Val), " in ", Formatted]}; format_reason_md({badarith, [MFA | _]}) -> {Md, Formatted} = format_mfa_md(MFA), - {[{reason, badarith} | Md], - ["bad arithmetic expression in ", Formatted]}; + {[{reason, badarith} | Md], ["bad arithmetic expression in ", Formatted]}; format_reason_md({{badmatch, Val}, [MFA | _]}) -> {Md, Formatted} = format_mfa_md(MFA), - {[{reason, badmatch} | Md], - ["no match of right hand value ", print_val(Val), " in ", Formatted]}; + {[{reason, badmatch} | Md], ["no match of right hand value ", print_val(Val), " in ", Formatted]}; format_reason_md({emfile, _Trace}) -> - {[{reason, emfile}], - "maximum number of file descriptors exhausted, check ulimit -n"}; + {[{reason, emfile}], "maximum number of file descriptors exhausted, check ulimit -n"}; format_reason_md({system_limit, [{M, F, _} | _] = Trace}) -> - Limit = case {M, F} of - {erlang, open_port} -> - "maximum number of ports exceeded"; - {erlang, spawn} -> - "maximum number of processes exceeded"; - {erlang, spawn_opt} -> - "maximum number of processes exceeded"; - {erlang, list_to_atom} -> - "tried to create an atom larger than 255, or maximum atom count exceeded"; - {ets, new} -> - "maximum number of ETS tables exceeded"; - _ -> - {Str, _} = rumTruncIo:print(Trace, 500), - Str - end, + Limit = + case {M, F} of + {erlang, open_port} -> + <<"maximum number of ports exceeded">>; + {erlang, spawn} -> + <<"maximum number of processes exceeded">>; + {erlang, spawn_opt} -> + <<"maximum number of processes exceeded">>; + {erlang, list_to_atom} -> + <<"tried to create an atom larger than 255, or maximum atom count exceeded">>; + {ets, new} -> + <<"maximum number of ETS tables exceeded">>; + _ -> + eFmt:formatBin(<<"~p">>, [Trace], [{charsLimit, 500}]) + end, {[{reason, system_limit}], ["system limit: ", Limit]}; format_reason_md({badarg, [MFA, MFA2 | _]}) -> case MFA of @@ -624,7 +619,7 @@ no_silent_hwm_drops_test_() -> application:set_env(lager, handlers, [{lager_test_backend, warning}]), application:set_env(lager, errLoggerRedirect, true), application:set_env(lager, errLoggerHwm, 5), - application:set_env(lager, error_logger_flush_queue, false), + application:set_env(lager, errLoggerFlushQueue, false), application:set_env(lager, suppress_supervisor_start_stop, true), application:set_env(lager, suppress_application_start_stop, true), application:unset_env(lager, crash_log), diff --git a/src/formatter/rumFormat.erl b/src/formatter/rumFormat.erl deleted file mode 100644 index 57749ad..0000000 --- a/src/formatter/rumFormat.erl +++ /dev/null @@ -1,526 +0,0 @@ --module(rumFormat). - -%% fork of io_lib_format that uses trunc_io to protect against large terms - --export([format/3, format/4]). - --record(options, { - chomp = false :: boolean() -}). - -format(FmtStr, Args, MaxLen) -> - format(FmtStr, Args, MaxLen, []). - -format([], [], _, _) -> - ""; -format(FmtStr, Args, MaxLen, Opts) when is_atom(FmtStr) -> - format(atom_to_list(FmtStr), Args, MaxLen, Opts); -format(FmtStr, Args, MaxLen, Opts) when is_binary(FmtStr) -> - format(binary_to_list(FmtStr), Args, MaxLen, Opts); -format(FmtStr, Args, MaxLen, Opts) when is_list(FmtStr) -> - case io_lib:deep_char_list(FmtStr) of - true -> - Options = make_options(Opts, #options{}), - Cs = collect(FmtStr, Args), - {Cs2, MaxLen2} = build(Cs, [], MaxLen, Options), - %% count how many terms remain - {Count, StrLen} = lists:foldl( - fun({_C, _As, _F, _Adj, _P, _Pad, _Enc}, {Terms, Chars}) -> - {Terms + 1, Chars}; - (_, {Terms, Chars}) -> - {Terms, Chars + 1} - end, {0, 0}, Cs2), - build2(Cs2, Count, MaxLen2 - StrLen); - false -> - erlang:error(badarg) - end; -format(_FmtStr, _Args, _MaxLen, _Opts) -> - erlang:error(badarg). - -collect([$~ | Fmt0], Args0) -> - {C, Fmt1, Args1} = collect_cseq(Fmt0, Args0), - [C | collect(Fmt1, Args1)]; -collect([C | Fmt], Args) -> - [C | collect(Fmt, Args)]; -collect([], []) -> []. - -collect_cseq(Fmt0, Args0) -> - {F, Ad, Fmt1, Args1} = field_width(Fmt0, Args0), - {P, Fmt2, Args2} = precision(Fmt1, Args1), - {Pad, Fmt3, Args3} = pad_char(Fmt2, Args2), - {Encoding, Fmt4, Args4} = encoding(Fmt3, Args3), - {C, As, Fmt5, Args5} = collect_cc(Fmt4, Args4), - {{C, As, F, Ad, P, Pad, Encoding}, Fmt5, Args5}. - -encoding([$t | Fmt], Args) -> - {unicode, Fmt, Args}; -encoding(Fmt, Args) -> - {latin1, Fmt, Args}. - -field_width([$- | Fmt0], Args0) -> - {F, Fmt, Args} = field_value(Fmt0, Args0), - field_width(-F, Fmt, Args); -field_width(Fmt0, Args0) -> - {F, Fmt, Args} = field_value(Fmt0, Args0), - field_width(F, Fmt, Args). - -field_width(F, Fmt, Args) when F < 0 -> - {-F, left, Fmt, Args}; -field_width(F, Fmt, Args) when F >= 0 -> - {F, right, Fmt, Args}. - -precision([$. | Fmt], Args) -> - field_value(Fmt, Args); -precision(Fmt, Args) -> - {none, Fmt, Args}. - -field_value([$* | Fmt], [A | Args]) when is_integer(A) -> - {A, Fmt, Args}; -field_value([C | Fmt], Args) when is_integer(C), C >= $0, C =< $9 -> - field_value([C | Fmt], Args, 0); -field_value(Fmt, Args) -> - {none, Fmt, Args}. - -field_value([C | Fmt], Args, F) when is_integer(C), C >= $0, C =< $9 -> - field_value(Fmt, Args, 10 * F + (C - $0)); -field_value(Fmt, Args, F) -> %Default case - {F, Fmt, Args}. - -pad_char([$., $* | Fmt], [Pad | Args]) -> {Pad, Fmt, Args}; -pad_char([$., Pad | Fmt], Args) -> {Pad, Fmt, Args}; -pad_char(Fmt, Args) -> {$\s, Fmt, Args}. - -%% collect_cc([FormatChar], [Argument]) -> -%% {Control,[ControlArg],[FormatChar],[Arg]}. -%% Here we collect the argments for each control character. -%% Be explicit to cause failure early. - -collect_cc([$w | Fmt], [A | Args]) -> {$w, [A], Fmt, Args}; -collect_cc([$p | Fmt], [A | Args]) -> {$p, [A], Fmt, Args}; -collect_cc([$W | Fmt], [A, Depth | Args]) -> {$W, [A, Depth], Fmt, Args}; -collect_cc([$P | Fmt], [A, Depth | Args]) -> {$P, [A, Depth], Fmt, Args}; -collect_cc([$s | Fmt], [A | Args]) -> {$s, [A], Fmt, Args}; -collect_cc([$e | Fmt], [A | Args]) -> {$e, [A], Fmt, Args}; -collect_cc([$f | Fmt], [A | Args]) -> {$f, [A], Fmt, Args}; -collect_cc([$g | Fmt], [A | Args]) -> {$g, [A], Fmt, Args}; -collect_cc([$b | Fmt], [A | Args]) -> {$b, [A], Fmt, Args}; -collect_cc([$B | Fmt], [A | Args]) -> {$B, [A], Fmt, Args}; -collect_cc([$x | Fmt], [A, Prefix | Args]) -> {$x, [A, Prefix], Fmt, Args}; -collect_cc([$X | Fmt], [A, Prefix | Args]) -> {$X, [A, Prefix], Fmt, Args}; -collect_cc([$+ | Fmt], [A | Args]) -> {$+, [A], Fmt, Args}; -collect_cc([$# | Fmt], [A | Args]) -> {$#, [A], Fmt, Args}; -collect_cc([$c | Fmt], [A | Args]) -> {$c, [A], Fmt, Args}; -collect_cc([$~ | Fmt], Args) when is_list(Args) -> {$~, [], Fmt, Args}; -collect_cc([$n | Fmt], Args) when is_list(Args) -> {$n, [], Fmt, Args}; -collect_cc([$i | Fmt], [A | Args]) -> {$i, [A], Fmt, Args}. - - -%% build([Control], Pc, Indentation) -> [Char]. -%% Interpret the control structures. Count the number of print -%% remaining and only calculate indentation when necessary. Must also -%% be smart when calculating indentation for characters in format. - -build([{$n, _, _, _, _, _, _}], Acc, MaxLen, #options{chomp = true}) -> - %% trailing ~n, ignore - {lists:reverse(Acc), MaxLen}; -build([{C, As, F, Ad, P, Pad, Enc} | Cs], Acc, MaxLen, O) -> - {S, MaxLen2} = control(C, As, F, Ad, P, Pad, Enc, MaxLen), - build(Cs, [S | Acc], MaxLen2, O); -build([$\n], Acc, MaxLen, #options{chomp = true}) -> - %% trailing \n, ignore - {lists:reverse(Acc), MaxLen}; -build([$\n | Cs], Acc, MaxLen, O) -> - build(Cs, [$\n | Acc], MaxLen - 1, O); -build([$\t | Cs], Acc, MaxLen, O) -> - build(Cs, [$\t | Acc], MaxLen - 1, O); -build([C | Cs], Acc, MaxLen, O) -> - build(Cs, [C | Acc], MaxLen - 1, O); -build([], Acc, MaxLen, _O) -> - {lists:reverse(Acc), MaxLen}. - -build2([{C, As, F, Ad, P, Pad, Enc} | Cs], Count, MaxLen) -> - {S, Len} = control2(C, As, F, Ad, P, Pad, Enc, MaxLen div Count), - [S | build2(Cs, Count - 1, MaxLen - Len)]; -build2([C | Cs], Count, MaxLen) -> - [C | build2(Cs, Count, MaxLen)]; -build2([], _, _) -> []. - -%% control(FormatChar, [Argument], FieldWidth, Adjust, Precision, PadChar, -%% Indentation) -> [Char] -%% This is the main dispatch function for the various formatting commands. -%% Field widths and precisions have already been calculated. - -control($e, [A], F, Adj, P, Pad, _Enc, L) when is_float(A) -> - Res = fwrite_e(A, F, Adj, P, Pad), - {Res, L - lists:flatlength(Res)}; -control($f, [A], F, Adj, P, Pad, _Enc, L) when is_float(A) -> - Res = fwrite_f(A, F, Adj, P, Pad), - {Res, L - lists:flatlength(Res)}; -control($g, [A], F, Adj, P, Pad, _Enc, L) when is_float(A) -> - Res = fwrite_g(A, F, Adj, P, Pad), - {Res, L - lists:flatlength(Res)}; -control($b, [A], F, Adj, P, Pad, _Enc, L) when is_integer(A) -> - Res = unprefixed_integer(A, F, Adj, base(P), Pad, true), - {Res, L - lists:flatlength(Res)}; -control($B, [A], F, Adj, P, Pad, _Enc, L) when is_integer(A) -> - Res = unprefixed_integer(A, F, Adj, base(P), Pad, false), - {Res, L - lists:flatlength(Res)}; -control($x, [A, Prefix], F, Adj, P, Pad, _Enc, L) when is_integer(A), - is_atom(Prefix) -> - Res = prefixed_integer(A, F, Adj, base(P), Pad, atom_to_list(Prefix), true), - {Res, L - lists:flatlength(Res)}; -control($x, [A, Prefix], F, Adj, P, Pad, _Enc, L) when is_integer(A) -> - true = io_lib:deep_char_list(Prefix), %Check if Prefix a character list - Res = prefixed_integer(A, F, Adj, base(P), Pad, Prefix, true), - {Res, L - lists:flatlength(Res)}; -control($X, [A, Prefix], F, Adj, P, Pad, _Enc, L) when is_integer(A), - is_atom(Prefix) -> - Res = prefixed_integer(A, F, Adj, base(P), Pad, atom_to_list(Prefix), false), - {Res, L - lists:flatlength(Res)}; -control($X, [A, Prefix], F, Adj, P, Pad, _Enc, L) when is_integer(A) -> - true = io_lib:deep_char_list(Prefix), %Check if Prefix a character list - Res = prefixed_integer(A, F, Adj, base(P), Pad, Prefix, false), - {Res, L - lists:flatlength(Res)}; -control($+, [A], F, Adj, P, Pad, _Enc, L) when is_integer(A) -> - Base = base(P), - Prefix = [integer_to_list(Base), $#], - Res = prefixed_integer(A, F, Adj, Base, Pad, Prefix, true), - {Res, L - lists:flatlength(Res)}; -control($#, [A], F, Adj, P, Pad, _Enc, L) when is_integer(A) -> - Base = base(P), - Prefix = [integer_to_list(Base), $#], - Res = prefixed_integer(A, F, Adj, Base, Pad, Prefix, false), - {Res, L - lists:flatlength(Res)}; -control($c, [A], F, Adj, P, Pad, unicode, L) when is_integer(A) -> - Res = char(A, F, Adj, P, Pad), - {Res, L - lists:flatlength(Res)}; -control($c, [A], F, Adj, P, Pad, _Enc, L) when is_integer(A) -> - Res = char(A band 255, F, Adj, P, Pad), - {Res, L - lists:flatlength(Res)}; -control($~, [], F, Adj, P, Pad, _Enc, L) -> - Res = char($~, F, Adj, P, Pad), - {Res, L - lists:flatlength(Res)}; -control($n, [], F, Adj, P, Pad, _Enc, L) -> - Res = newline(F, Adj, P, Pad), - {Res, L - lists:flatlength(Res)}; -control($i, [_A], _F, _Adj, _P, _Pad, _Enc, L) -> - {[], L}; -control($s, [A], F, Adj, P, Pad, _Enc, L) when is_atom(A) -> - Res = string(atom_to_list(A), F, Adj, P, Pad), - {Res, L - lists:flatlength(Res)}; -control(C, A, F, Adj, P, Pad, Enc, L) -> - %% save this for later - these are all the 'large' terms - {{C, A, F, Adj, P, Pad, Enc}, L}. - -control2($w, [A], F, Adj, P, Pad, _Enc, L) -> - Term = rumTruncIo:fprint(A, L, [{lists_as_strings, false}]), - Res = term(Term, F, Adj, P, Pad), - {Res, lists:flatlength(Res)}; -control2($p, [A], _F, _Adj, _P, _Pad, _Enc, L) -> - Term = rumTruncIo:fprint(A, L, [{lists_as_strings, true}]), - {Term, lists:flatlength(Term)}; -control2($W, [A, Depth], F, Adj, P, Pad, _Enc, L) when is_integer(Depth) -> - Term = rumTruncIo:fprint(A, L, [{depth, Depth}, {lists_as_strings, false}]), - Res = term(Term, F, Adj, P, Pad), - {Res, lists:flatlength(Res)}; -control2($P, [A, Depth], _F, _Adj, _P, _Pad, _Enc, L) when is_integer(Depth) -> - Term = rumTruncIo:fprint(A, L, [{depth, Depth}, {lists_as_strings, true}]), - {Term, lists:flatlength(Term)}; -control2($s, [L0], F, Adj, P, Pad, latin1, L) -> - List = rumTruncIo:fprint(iolist_to_chars(L0), L, [{force_strings, true}]), - Res = string(List, F, Adj, P, Pad), - {Res, lists:flatlength(Res)}; -control2($s, [L0], F, Adj, P, Pad, unicode, L) -> - List = rumTruncIo:fprint(cdata_to_chars(L0), L, [{force_strings, true}]), - Res = uniconv(string(List, F, Adj, P, Pad)), - {Res, lists:flatlength(Res)}. - -iolist_to_chars([C | Cs]) when is_integer(C), C >= $\000, C =< $\377 -> - [C | iolist_to_chars(Cs)]; -iolist_to_chars([I | Cs]) -> - [iolist_to_chars(I) | iolist_to_chars(Cs)]; -iolist_to_chars([]) -> - []; -iolist_to_chars(B) when is_binary(B) -> - binary_to_list(B). - -cdata_to_chars([C | Cs]) when is_integer(C), C >= $\000 -> - [C | cdata_to_chars(Cs)]; -cdata_to_chars([I | Cs]) -> - [cdata_to_chars(I) | cdata_to_chars(Cs)]; -cdata_to_chars([]) -> - []; -cdata_to_chars(B) when is_binary(B) -> - case catch unicode:characters_to_list(B) of - L when is_list(L) -> L; - _ -> binary_to_list(B) - end. - -make_options([], Options) -> - Options; -make_options([{chomp, Bool} | T], Options) when is_boolean(Bool) -> - make_options(T, Options#options{chomp = Bool}). - --ifdef(UNICODE_AS_BINARIES). -uniconv(C) -> - unicode:characters_to_binary(C, unicode). --else. -uniconv(C) -> - C. --endif. -%% Default integer base -base(none) -> - 10; -base(B) when is_integer(B) -> - B. - -%% term(TermList, Field, Adjust, Precision, PadChar) -%% Output the characters in a term. -%% Adjust the characters within the field if length less than Max padding -%% with PadChar. - -term(T, none, _Adj, none, _Pad) -> T; -term(T, none, Adj, P, Pad) -> term(T, P, Adj, P, Pad); -term(T, F, Adj, P0, Pad) -> - L = lists:flatlength(T), - P = case P0 of none -> erlang:min(L, F); _ -> P0 end, - if - L > P -> - adjust(chars($*, P), chars(Pad, F - P), Adj); - F >= P -> - adjust(T, chars(Pad, F - L), Adj) - end. - -%% fwrite_e(Float, Field, Adjust, Precision, PadChar) - -fwrite_e(Fl, none, Adj, none, Pad) -> %Default values - fwrite_e(Fl, none, Adj, 6, Pad); -fwrite_e(Fl, none, _Adj, P, _Pad) when P >= 2 -> - float_e(Fl, float_data(Fl), P); -fwrite_e(Fl, F, Adj, none, Pad) -> - fwrite_e(Fl, F, Adj, 6, Pad); -fwrite_e(Fl, F, Adj, P, Pad) when P >= 2 -> - term(float_e(Fl, float_data(Fl), P), F, Adj, F, Pad). - -float_e(Fl, Fd, P) when Fl < 0.0 -> %Negative numbers - [$- | float_e(-Fl, Fd, P)]; -float_e(_Fl, {Ds, E}, P) -> - case float_man(Ds, 1, P - 1) of - {[$0 | Fs], true} -> [[$1 | Fs] | float_exp(E)]; - {Fs, false} -> [Fs | float_exp(E - 1)] - end. - -%% float_man([Digit], Icount, Dcount) -> {[Chars],CarryFlag}. -%% Generate the characters in the mantissa from the digits with Icount -%% characters before the '.' and Dcount decimals. Handle carry and let -%% caller decide what to do at top. - -float_man(Ds, 0, Dc) -> - {Cs, C} = float_man(Ds, Dc), - {[$. | Cs], C}; -float_man([D | Ds], I, Dc) -> - case float_man(Ds, I - 1, Dc) of - {Cs, true} when D =:= $9 -> {[$0 | Cs], true}; - {Cs, true} -> {[D + 1 | Cs], false}; - {Cs, false} -> {[D | Cs], false} - end; -float_man([], I, Dc) -> %Pad with 0's - {string:chars($0, I, [$. | string:chars($0, Dc)]), false}. - -float_man([D | _], 0) when D >= $5 -> {[], true}; -float_man([_ | _], 0) -> {[], false}; -float_man([D | Ds], Dc) -> - case float_man(Ds, Dc - 1) of - {Cs, true} when D =:= $9 -> {[$0 | Cs], true}; - {Cs, true} -> {[D + 1 | Cs], false}; - {Cs, false} -> {[D | Cs], false} - end; -float_man([], Dc) -> {string:chars($0, Dc), false}. %Pad with 0's - -%% float_exp(Exponent) -> [Char]. -%% Generate the exponent of a floating point number. Always include sign. - -float_exp(E) when E >= 0 -> - [$e, $+ | integer_to_list(E)]; -float_exp(E) -> - [$e | integer_to_list(E)]. - -%% fwrite_f(FloatData, Field, Adjust, Precision, PadChar) - -fwrite_f(Fl, none, Adj, none, Pad) -> %Default values - fwrite_f(Fl, none, Adj, 6, Pad); -fwrite_f(Fl, none, _Adj, P, _Pad) when P >= 1 -> - float_f(Fl, float_data(Fl), P); -fwrite_f(Fl, F, Adj, none, Pad) -> - fwrite_f(Fl, F, Adj, 6, Pad); -fwrite_f(Fl, F, Adj, P, Pad) when P >= 1 -> - term(float_f(Fl, float_data(Fl), P), F, Adj, F, Pad). - -float_f(Fl, Fd, P) when Fl < 0.0 -> - [$- | float_f(-Fl, Fd, P)]; -float_f(Fl, {Ds, E}, P) when E =< 0 -> - float_f(Fl, {string:chars($0, -E + 1, Ds), 1}, P); %Prepend enough 0's -float_f(_Fl, {Ds, E}, P) -> - case float_man(Ds, E, P) of - {Fs, true} -> "1" ++ Fs; %Handle carry - {Fs, false} -> Fs - end. - -%% float_data([FloatChar]) -> {[Digit],Exponent} - -float_data(Fl) -> - float_data(float_to_list(Fl), []). - -float_data([$e | E], Ds) -> - {lists:reverse(Ds), list_to_integer(E) + 1}; -float_data([D | Cs], Ds) when D >= $0, D =< $9 -> - float_data(Cs, [D | Ds]); -float_data([_ | Cs], Ds) -> - float_data(Cs, Ds). - -%% fwrite_g(Float, Field, Adjust, Precision, PadChar) -%% Use the f form if Float is >= 0.1 and < 1.0e4, -%% and the prints correctly in the f form, else the e form. -%% Precision always means the # of significant digits. - -fwrite_g(Fl, F, Adj, none, Pad) -> - fwrite_g(Fl, F, Adj, 6, Pad); -fwrite_g(Fl, F, Adj, P, Pad) when P >= 1 -> - A = abs(Fl), - E = if A < 1.0e-1 -> -2; - A < 1.0e0 -> -1; - A < 1.0e1 -> 0; - A < 1.0e2 -> 1; - A < 1.0e3 -> 2; - A < 1.0e4 -> 3; - true -> fwrite_f - end, - if P =< 1, E =:= -1; - P - 1 > E, E >= -1 -> - fwrite_f(Fl, F, Adj, P - 1 - E, Pad); - P =< 1 -> - fwrite_e(Fl, F, Adj, 2, Pad); - true -> - fwrite_e(Fl, F, Adj, P, Pad) - end. - - -%% string(String, Field, Adjust, Precision, PadChar) - -string(S, none, _Adj, none, _Pad) -> S; -string(S, F, Adj, none, Pad) -> - string_field(S, F, Adj, lists:flatlength(S), Pad); -string(S, none, _Adj, P, Pad) -> - string_field(S, P, left, lists:flatlength(S), Pad); -string(S, F, Adj, P, Pad) when F >= P -> - N = lists:flatlength(S), - if F > P -> - if N > P -> - adjust(flat_trunc(S, P), chars(Pad, F - P), Adj); - N < P -> - adjust([S | chars(Pad, P - N)], chars(Pad, F - P), Adj); - true -> % N == P - adjust(S, chars(Pad, F - P), Adj) - end; - true -> % F == P - string_field(S, F, Adj, N, Pad) - end. - -string_field(S, F, _Adj, N, _Pad) when N > F -> - flat_trunc(S, F); -string_field(S, F, Adj, N, Pad) when N < F -> - adjust(S, chars(Pad, F - N), Adj); -string_field(S, _, _, _, _) -> % N == F - S. - -%% unprefixed_integer(Int, Field, Adjust, Base, PadChar, Lowercase) -%% -> [Char]. - -unprefixed_integer(Int, F, Adj, Base, Pad, Lowercase) - when Base >= 2, Base =< 1 + $Z - $A + 10 -> - if Int < 0 -> - S = cond_lowercase(erlang:integer_to_list(-Int, Base), Lowercase), - term([$- | S], F, Adj, none, Pad); - true -> - S = cond_lowercase(erlang:integer_to_list(Int, Base), Lowercase), - term(S, F, Adj, none, Pad) - end. - -%% prefixed_integer(Int, Field, Adjust, Base, PadChar, Prefix, Lowercase) -%% -> [Char]. - -prefixed_integer(Int, F, Adj, Base, Pad, Prefix, Lowercase) - when Base >= 2, Base =< 1 + $Z - $A + 10 -> - if Int < 0 -> - S = cond_lowercase(erlang:integer_to_list(-Int, Base), Lowercase), - term([$-, Prefix | S], F, Adj, none, Pad); - true -> - S = cond_lowercase(erlang:integer_to_list(Int, Base), Lowercase), - term([Prefix | S], F, Adj, none, Pad) - end. - -%% char(Char, Field, Adjust, Precision, PadChar) -> [Char]. - -char(C, none, _Adj, none, _Pad) -> [C]; -char(C, F, _Adj, none, _Pad) -> chars(C, F); -char(C, none, _Adj, P, _Pad) -> chars(C, P); -char(C, F, Adj, P, Pad) when F >= P -> - adjust(chars(C, P), chars(Pad, F - P), Adj). - -%% newline(Field, Adjust, Precision, PadChar) -> [Char]. - -newline(none, _Adj, _P, _Pad) -> "\n"; -newline(F, right, _P, _Pad) -> chars($\n, F). - -%% -%% Utilities -%% - -adjust(Data, [], _) -> Data; -adjust(Data, Pad, left) -> [Data | Pad]; -adjust(Data, Pad, right) -> [Pad | Data]. - -%% Flatten and truncate a deep list to at most N elements. -flat_trunc(List, N) when is_integer(N), N >= 0 -> - flat_trunc(List, N, []). - -flat_trunc(L, 0, R) when is_list(L) -> - lists:reverse(R); -flat_trunc([H | T], N, R) -> - flat_trunc(T, N - 1, [H | R]); -flat_trunc([], _, R) -> - lists:reverse(R). - -%% A deep version of string:chars/2,3 - -chars(_C, 0) -> - []; -chars(C, 1) -> - [C]; -chars(C, 2) -> - [C, C]; -chars(C, 3) -> - [C, C, C]; -chars(C, N) when is_integer(N), (N band 1) =:= 0 -> - S = chars(C, N bsr 1), - [S | S]; -chars(C, N) when is_integer(N) -> - S = chars(C, N bsr 1), - [C, S | S]. - -%chars(C, N, Tail) -> -% [chars(C, N)|Tail]. - -%% Lowercase conversion - -cond_lowercase(String, true) -> - lowercase(String); -cond_lowercase(String, false) -> - String. - -lowercase([H | T]) when is_integer(H), H >= $A, H =< $Z -> - [(H - $A + $a) | lowercase(T)]; -lowercase([H | T]) -> - [H | lowercase(T)]; -lowercase([]) -> - []. diff --git a/src/test/lager_common_test_backend.erl b/src/test/lager_common_test_backend.erl index 8bec770..ba9b844 100644 --- a/src/test/lager_common_test_backend.erl +++ b/src/test/lager_common_test_backend.erl @@ -49,7 +49,7 @@ bounce(Level) -> ok = eRum:start(), %% we care more about getting all of our messages here than being %% careful with the amount of memory that we're using. - rumErrLoggerH:set_high_water(100000), + rumErrLoggerH:setHighWater(100000), ok. -spec(init(integer()|atom()|[term()]) -> {ok, #state{}} | {error, atom()}).