diff --git a/README.md b/README.md index fc06f61..08d0268 100644 --- a/README.md +++ b/README.md @@ -355,20 +355,20 @@ The module should provide the following callbacks as `lager_rotator_behaviour` ```erlang %% @doc Create a log file --callback(createLogfile(Name :: list(), Buffer :: {integer(), integer()} | any()) -> +-callback(createLogFile(Name :: list(), Buffer :: {integer(), integer()} | any()) -> {ok, {FD :: file:io_device(), Inode :: integer(), Size :: integer()}} | {error, any()}). %% @doc Open a log file --callback(openLogfile(Name :: list(), Buffer :: {integer(), integer()} | any()) -> +-callback(openLogFile(Name :: list(), Buffer :: {integer(), integer()} | any()) -> {ok, {FD :: file:io_device(), Inode :: integer(), Size :: integer()}} | {error, any()}). %% @doc Ensure reference to current target, could be rotated --callback(ensureLogfile(Name :: list(), FD :: file:io_device(), Inode :: integer(), +-callback(ensureLogFile(Name :: list(), FD :: file:io_device(), Inode :: integer(), Buffer :: {integer(), integer()} | any()) -> {ok, {FD :: file:io_device(), Inode :: integer(), Size :: integer()}} | {error, any()}). %% @doc Rotate the log file --callback(rotateLogfile(Name :: list(), Count :: integer()) -> +-callback(rotateLogFile(Name :: list(), Count :: integer()) -> ok). ``` diff --git a/eRum.sample.config b/eRum.sample.config index fb55761..93d5f2e 100644 --- a/eRum.sample.config +++ b/eRum.sample.config @@ -16,7 +16,7 @@ ]}, %% ******************************************** format相关 ****************************************************** - {metadata_whitelist, []]}, + {metadata_whitelist, []}, {reverse_pretty_stacktrace, true}, %%*********************************************** 异步日志相关 ***************************************************** diff --git a/include/eRum.hrl b/include/eRum.hrl index 2635f5f..11ae6f3 100644 --- a/include/eRum.hrl +++ b/include/eRum.hrl @@ -7,6 +7,10 @@ -define(Print(Args), io:format("IMY************~p~n", [Args])). +-define(LAGER_MD_KEY, '__lager_metadata'). +-define(TRACE_SINK, '__trace_sink'). +-define(ROTATE_TIMEOUT, 100000). + %% 应用名字 -define(RumAppName, eRum). @@ -16,6 +20,30 @@ -define(RumDefSink, rumEvent). -define(RumErrLogSink, error_logger_lager_event). +-type rumConsoleOpt() :: + {id, atom() | {atom(), atom()}} | + {use_stderr, boolean()} | + {group_leader, false | pid() | atom()} | + {formatter, atom()} | + {formatter_config, list()}. + +-type rumFileOpt() :: + {file, string()} | + {level, rumAtomLevel()} | + {size, non_neg_integer()} | + {date, string()} | + {count, non_neg_integer()} | + {rotator, atom()} | + {high_water_mark, non_neg_integer()} | + {flush_queue, boolean()} | + {flush_threshold, non_neg_integer()} | + {sync_interval, non_neg_integer()} | + {sync_size, non_neg_integer()} | + {sync_on, rumAtomLevel()} | + {check_interval, non_neg_integer()} | + {formatter, atom()} | + {formatter_config, term()}. + %% BkdFile默认配置 -define(RumDefLogLevel, info). -define(RumDefRotateSize, 10485760). %% 10mb diff --git a/src/backend/rumBkdConsole.erl b/src/backend/rumBkdConsole.erl index 1302aac..c78c17c 100644 --- a/src/backend/rumBkdConsole.erl +++ b/src/backend/rumBkdConsole.erl @@ -14,6 +14,10 @@ -compile([{parse_transform, rumTransform}]). -endif. +-define(TERSE_FORMAT, [time, " ", color, "[", severity, "] ", message]). +-define(RumDefConsoleFmtCfg, ?TERSE_FORMAT ++ [eol()]). +-define(RumDefConsoleOpts, [{use_stderr, false}, {group_leader, false}, {id, ?MODULE}, {formatter, rumFormatter}, {formatter_config, ?RumDefConsoleFmtCfg}]). + -export([ init/1 , handleCall/2 @@ -23,31 +27,24 @@ , code_change/3 ]). --define(TERSE_FORMAT,[time, " ", color, "[", severity,"] ", message]). --define(DEFAULT_FORMAT_CONFIG, ?TERSE_FORMAT ++ [eol()]). --define(FORMAT_CONFIG_OFF, [{eol, eol()}]). --define(DefOpts, [{use_stderr, false}, {group_leader, false}, {id, ?MODULE}, {formatter, rumFormatter}, {formatter_config, ?DEFAULT_FORMAT_CONFIG}]). - -record(state, { - level :: rumMaskLevel(), - out = user :: user | standard_error | pid(), - id :: atom() | {atom(), any()}, - formatter :: atom(), - formatConfig :: any(), - colors = [] :: list() + id :: atom() | {atom(), any()} + , level :: rumMaskLevel() + , out = user :: user | standard_error | pid() + , formatter :: atom() + , formatCfg :: any() + , colors = [] :: list() }). - +-spec init([rumConsoleOpt(), ...]) -> {ok, #state{}} | {error, atom()}. init(Opts) -> - case isNewStyleConsole() of + case isNewStyleConsole() of false -> Msg = "Lager's console backend is incompatible with the 'old' shell, not enabling it", %% be as noisy as possible, log to every possible place - try - alarm_handler:set_alarm({?MODULE, "WARNING: " ++ Msg}) + try alarm_handler:set_alarm({?MODULE, "WARNING: " ++ Msg}) catch - _:_ -> - error_logger:warning_msg(Msg ++ "~n") + _:_ -> error_logger:warning_msg(Msg ++ "~n") end, io:format("WARNING: " ++ Msg ++ "~n"), ?INT_LOG(warning, Msg, []), @@ -57,17 +54,17 @@ init(Opts) -> Colors = ?IIF(rumUtil:get_env(colored, false), rumUtil:get_env(colors, []), []), Level = rumUtil:get_opt(level, Opts, undefined), LevelMask = rumUtil:configToMask(Level), - [UseErr, GroupLeader, Id, Formatter, Config] = [rumUtil:get_opt(Key, Opts, Def) || {Key, Def} <- ?DefOpts], + [UseErr, GroupLeader, Id, Formatter, Config] = [rumUtil:get_opt(Key, Opts, Def) || {Key, Def} <- ?RumDefConsoleOpts], Out = ?IIF(UseErr, standard_error, ?IIF(GroupLeader == false, user, begin erlang:monitor(process, GroupLeader), GroupLeader end)), - {ok, #state{level = LevelMask, id = Id, out = Out, formatter = Formatter, formatConfig = Config, colors = Colors}} + {ok, #state{level = LevelMask, id = Id, out = Out, formatter = Formatter, formatCfg = Config, colors = Colors}} end. checkOpts([]) -> true; -checkOpts([{level, L} | T]) when is_atom(L) -> - ?IIF(lists:member(L, ?RumLevels) == false, {error, {bad_level, L}}, checkOpts(T)); -checkOpts([{use_stderr, true} | T]) -> +checkOpts([{id, {?MODULE, _}} | T]) -> checkOpts(T); -checkOpts([{use_stderr, false} | T]) -> +checkOpts([{level, Level} | T]) -> + ?IIF(rumUtil:validateLogLevel(Level) /= false, checkOpts(T), {error, {bad_level, Level}}); +checkOpts([{use_stderr, Flag} | T]) when is_boolean(Flag) -> checkOpts(T); checkOpts([{formatter, M} | T]) when is_atom(M) -> checkOpts(T); @@ -75,26 +72,23 @@ checkOpts([{formatter_config, C} | T]) when is_list(C) -> checkOpts(T); checkOpts([{group_leader, L} | T]) when is_pid(L) -> checkOpts(T); -checkOpts([{id, {?MODULE, _}} | T]) -> - checkOpts(T); checkOpts([H | _]) -> {error, {invalid_opt, H}}. -handleCall(mGetLogLevel, #state{level = Level} = State) -> - {reply, Level, State}; +handleCall(mGetLogLevel, State) -> + {reply, State#state.level, State}; handleCall({mSetLogLevel, Level}, State) -> - try rumUtil:configToMask(Level) of - Levels -> - {reply, ok, State#state{level = Levels}} - catch - _:_ -> - {reply, {error, bad_log_level}, State} + case rumUtil:validateLogLevel(Level) of + false -> + {reply, {error, bad_loglevel}, State}; + LevelMask -> + {reply, ok, State#state{level = LevelMask}} end; handleCall(_Msg, State) -> ?ERR("~p call receive unexpect msg ~p ~n ", [?MODULE, _Msg]), {reply, ok, State}. -handleEvent({mWriteLog, Message}, #state{level = Level, out = Out, formatter = Formatter, formatConfig = FormatConfig, colors = Colors, id = ID}) -> +handleEvent({mWriteLog, Message}, #state{level = Level, out = Out, formatter = Formatter, formatCfg = FormatConfig, colors = Colors, id = ID}) -> case rumUtil:isLoggAble(Message, Level, ID) of true -> io:put_chars(Out, Formatter:format(Message, FormatConfig, Colors)), @@ -112,9 +106,9 @@ handleInfo(_Msg, _State) -> ?ERR("~p info receive unexpect msg ~p ~n ", [?MODULE, _Msg]), kpS. -terminate(removeEpm, _State = #state{id = ID}) -> +terminate(removeEpm, State) -> %% have to do this asynchronously because we're in the event handlr - spawn(fun() -> eRum:clear_trace_by_destination(ID) end), + spawn(fun() -> eRum:clear_trace_by_destination(State#state.id) end), ok; terminate(_Reason, _State) -> ok. @@ -329,7 +323,7 @@ console_log_test_() -> register(user, Pid), gen_event:add_handler(rumEvent, lager_console_backend, [{level, info}]), rumConfig:set({rumEvent, loglevel}, {rumUtil:configToMask(info), []}), - eRum:set_loglevel(lager_console_backend, '!=info'), + eRum:setLogLevel(lager_console_backend, '!=info'), erlang:group_leader(Pid, whereis(rumEvent)), eRum:debug("Test message"), receive @@ -360,7 +354,7 @@ console_log_test_() -> register(user, Pid), gen_event:add_handler(rumEvent, lager_console_backend, [{level, info}]), rumConfig:set({rumEvent, loglevel}, {rumUtil:configToMask(info), []}), - eRum:set_loglevel(lager_console_backend, '=debug'), + eRum:setLogLevel(lager_console_backend, '=debug'), erlang:group_leader(Pid, whereis(rumEvent)), eRum:debug("Test message"), receive @@ -487,22 +481,22 @@ set_loglevel_test_() -> [ {"Get/set loglevel test", fun() -> - ?assertEqual(info, eRum:get_loglevel(lager_console_backend)), - eRum:set_loglevel(lager_console_backend, debug), - ?assertEqual(debug, eRum:get_loglevel(lager_console_backend)), - eRum:set_loglevel(lager_console_backend, '!=debug'), - ?assertEqual(info, eRum:get_loglevel(lager_console_backend)), - eRum:set_loglevel(lager_console_backend, '!=info'), - ?assertEqual(debug, eRum:get_loglevel(lager_console_backend)), + ?assertEqual(info, eRum:getLogLevel(lager_console_backend)), + eRum:setLogLevel(lager_console_backend, debug), + ?assertEqual(debug, eRum:getLogLevel(lager_console_backend)), + eRum:setLogLevel(lager_console_backend, '!=debug'), + ?assertEqual(info, eRum:getLogLevel(lager_console_backend)), + eRum:setLogLevel(lager_console_backend, '!=info'), + ?assertEqual(debug, eRum:getLogLevel(lager_console_backend)), ok end }, {"Get/set invalid loglevel test", fun() -> - ?assertEqual(info, eRum:get_loglevel(lager_console_backend)), + ?assertEqual(info, eRum:getLogLevel(lager_console_backend)), ?assertEqual({error, bad_log_level}, - eRum:set_loglevel(lager_console_backend, fatfinger)), - ?assertEqual(info, eRum:get_loglevel(lager_console_backend)) + eRum:setLogLevel(lager_console_backend, fatfinger)), + ?assertEqual(info, eRum:getLogLevel(lager_console_backend)) end } diff --git a/src/backend/rumBkdFile.erl b/src/backend/rumBkdFile.erl index 51abc67..ec29626 100644 --- a/src/backend/rumBkdFile.erl +++ b/src/backend/rumBkdFile.erl @@ -52,24 +52,7 @@ osType :: atom() }). --type option() :: -{file, string()} | -{level, rumAtomLevel()} | -{size, non_neg_integer()} | -{date, string()} | -{count, non_neg_integer()} | -{rotator, atom()} | -{high_water_mark, non_neg_integer()} | -{flush_queue, boolean()} | -{flush_threshold, non_neg_integer()} | -{sync_interval, non_neg_integer()} | -{sync_size, non_neg_integer()} | -{sync_on, rumAtomLevel()} | -{check_interval, non_neg_integer()} | -{formatter, atom()} | -{formatter_config, term()}. - --spec init([option(), ...]) -> {ok, #state{}} | {error, {fatal, bad_config}}. +-spec init([rumFileOpt(), ...]) -> {ok, #state{}} | {error, atom()}. init(Opts) -> true = checkOpts(Opts, false), RelName = rumUtil:get_opt(file, Opts, undefined), @@ -89,8 +72,8 @@ init(Opts) -> FormatterConfig = rumUtil:get_opt(formatter_config, Opts, ?RumDefFormatterCfg), %% 需要二次转换的配置在这里处理 - Level = validateLogLevel(CfgLevel), - SyncOn = validateLogLevel(CfgSyncOn), + Level = rumUtil:configToMask(CfgLevel), + SyncOn = rumUtil:configToMask(CfgSyncOn), CheckInterval = ?IIF(CfgCheckInterval == always, 0, CfgCheckInterval), {ok, Date} = rumUtil:parseRotateSpec(CfgDate), FileName = rumUtil:parsePath(RelName), @@ -105,8 +88,8 @@ init(Opts) -> , syncSize = SyncSize, checkInterval = CheckInterval }, case Rotator:createLogFile(FileName, {SyncSize, SyncInterval}) of - {ok, Fd, Inode, Ctime, _Size} -> - {ok, TemState#state{fd = Fd, inode = Inode, ctime = Ctime}}; + {ok, Fd, Inode, CTime, _Size} -> + {ok, TemState#state{fd = Fd, inode = Inode, ctime = CTime}}; {error, Reason} -> ?INT_LOG(error, "Failed to open log file ~ts with error ~s", [FileName, file:format_error(Reason)]), {ok, TemState#state{flap = true}} @@ -115,12 +98,12 @@ init(Opts) -> handleCall(mGetLogLevel, #state{level = Level} = State) -> {reply, Level, State}; handleCall({mSetLogLevel, Level}, #state{fileName = Ident} = State) -> - case validateLogLevel(Level) of + case rumUtil:validateLogLevel(Level) of false -> {reply, {error, bad_loglevel}, State}; - Levels -> + LevelMask -> ?INT_LOG(notice, "Changed loglevel of ~s to ~p", [Ident, Level]), - {reply, ok, State#state{level = Levels}} + {reply, ok, State#state{level = LevelMask}} end; handleCall({mSetLogHwm, Hwm}, #state{shaper = Shaper, fileName = FileName} = State) -> @@ -168,7 +151,7 @@ handleEvent(_Msg, _State) -> handleInfo({mRotate, File}, #state{fileName = File, count = Count, date = Date, rotator = Rotator} = State) -> NewState = closeFile(State), - _ = Rotator:rotateLogfile(File, Count), + _ = Rotator:rotateLogFile(File, Count), scheduleRotation(File, Date), {ok, NewState}; handleInfo({mShaperExpired, Name}, #state{shaper = Shaper, fileName = Name, formatter = Formatter, formatterConfig = FormatConfig} = State) -> @@ -197,14 +180,14 @@ writeLog(#state{fileName = FileName, fd = Fd, inode = Inode, ctime = Ctime, flap case isWriteCheck(Fd, LastCheck, CheckInterval, FileName, Inode, Ctime, Timestamp) of true -> %% need to check for rotation - case Rotator:ensureLogfile(FileName, Fd, Inode, Ctime, {SyncSize, SyncInterval}) of + case Rotator:ensureLogFile(FileName, Fd, Inode, Ctime, {SyncSize, SyncInterval}) of {ok, NewFD, NewInode, NewCtime, FileSize} -> case RotSize > 0 andalso FileSize > RotSize of true -> TemState = closeFile(State), - case Rotator:rotateLogfile(FileName, Count) of + case Rotator:rotateLogFile(FileName, Count) of ok -> - %% go around the loop again, we'll do another rotation check and hit the next clause of ensureLogfile + %% go around the loop again, we'll do another rotation check and hit the next clause of ensureLogFile writeLog(TemState, Timestamp, Level, Msg); {error, Reason} -> ?IIF(Flap, State, begin ?INT_LOG(error, "Failed to rotate log file ~ts with error ~s", [FileName, file:format_error(Reason)]), State#state{flap = true} end) @@ -242,49 +225,32 @@ writeFile(#state{fd = Fd, fileName = FileName, flap = Flap, syncOn = SyncOn} = S State end. -isWriteCheck(Fd, LastCheck, CheckInterval, Name, Inode, Ctime, Timestamp) -> - LastCheck1 = abs(Timestamp - LastCheck), - case LastCheck1 >= CheckInterval orelse Fd == undefined of +isWriteCheck(Fd, LastCheck, CheckInterval, Name, Inode, CTime, Timestamp) -> + DiffTime = abs(Timestamp - LastCheck), + case DiffTime >= CheckInterval orelse Fd == undefined of true -> true; _ -> % We need to know if the file has changed "out from under lager" so we don't write to an invalid Fd - {Result, _FInfo} = rumUtil:isFileChanged(Name, Inode, Ctime), + {Result, _FInfo} = rumUtil:isFileChanged(Name, Inode, CTime), Result end. %% Convert the config into a gen_event handler ID -configToId({Name, _Severity}) when is_list(Name) -> - {?MODULE, Name}; -configToId({Name, _Severity, _Size, _Rotation, _Count}) -> - {?MODULE, Name}; -configToId([{Name, _Severity, _Size, _Rotation, _Count}, _Format]) -> - {?MODULE, Name}; -configToId([{Name, _Severity}, _Format]) when is_list(Name) -> - {?MODULE, Name}; configToId(Config) -> - case proplists:get_value(file, Config) of + case rumUtil:get_opt(file, Config, undefined) of undefined -> erlang:error(no_file); File -> {?MODULE, File} end. -validateLogLevel(Level) -> - try rumUtil:configToMask(Level) of - Levels -> - Levels - catch - _:_ -> - false - end. - checkOpts([], IsFile) -> ?IIF(IsFile, true, {error, no_file_name}); checkOpts([{file, _File} | Tail], _IsFile) -> checkOpts(Tail, true); checkOpts([{level, Level} | Tail], IsFile) -> - ?IIF(validateLogLevel(Level) /= false, checkOpts(Tail, IsFile), ({error, {invalid_log_level, Level}})); + ?IIF(rumUtil:validateLogLevel(Level) /= false, checkOpts(Tail, IsFile), {error, {invalid_log_level, Level}}); checkOpts([{size, Size} | Tail], IsFile) when is_integer(Size), Size >= 0 -> checkOpts(Tail, IsFile); checkOpts([{count, Count} | Tail], IsFile) when is_integer(Count), Count >= 0 -> @@ -301,8 +267,8 @@ checkOpts([{sync_size, SyncSize} | Tail], IsFile) when is_integer(SyncSize), Syn checkOpts(Tail, IsFile); checkOpts([{check_interval, CheckInt} | Tail], IsFile) when is_integer(CheckInt), CheckInt >= 0; CheckInt == always -> checkOpts(Tail, IsFile); -checkOpts([{sync_on, _Level} | Tail], IsFile) -> - checkOpts(Tail, IsFile); +checkOpts([{sync_on, Level} | Tail], IsFile) -> + ?IIF(rumUtil:validateLogLevel(Level) /= false, checkOpts(Tail, IsFile), {error, {invalid_sync_on, Level}}); checkOpts([{formatter, Fmt} | Tail], IsFile) when is_atom(Fmt) -> checkOpts(Tail, IsFile); checkOpts([{formatter_config, FmtCfg} | Tail], IsFile) when is_list(FmtCfg) -> @@ -345,7 +311,7 @@ get_loglevel_test() -> rotation_test_() -> {foreach, fun() -> - SyncLevel = validateLogLevel(?RumDefSyncLevel), + SyncLevel = rumUtil:configToMask(?RumDefSyncLevel), SyncSize = ?RumDefSyncSize, SyncInterval = ?RumDefSyncInterval, Rotator = ?RumDefRotateMod, @@ -736,7 +702,7 @@ filesystem_test_() -> {ok, Bin} = file:read_file(TestLog), Lines = length(re:split(Bin, "\n", [{return, list}, trim])), ?assertEqual(Lines, 2), - ?assertEqual(ok, eRum:set_loglevel(lager_file_backend, TestLog, warning)), + ?assertEqual(ok, eRum:setLogLevel(lager_file_backend, TestLog, warning)), eRum:log(info, self(), "Test message3"), %% this won't get logged eRum:log(error, self(), "Test message4"), {ok, Bin2} = file:read_file(TestLog), @@ -752,7 +718,7 @@ filesystem_test_() -> gen_event:add_handler(rumEvent, lager_file_backend, [{TestLog, info, 10 * 1024 * 1024, "$D0", 5}, {lager_default_formatter}]), gen_event:add_handler(rumEvent, lager_file_backend, {TestLog3, info}), - ?assertEqual({error, bad_module}, eRum:set_loglevel(lager_file_backend, TestLog, warning)) + ?assertEqual({error, bad_module}, eRum:setLogLevel(lager_file_backend, TestLog, warning)) end}, {"tracing should work", fun() -> diff --git a/src/crashLog/rumCrashLog.erl b/src/crashLog/rumCrashLog.erl index 24be013..1afc5bb 100644 --- a/src/crashLog/rumCrashLog.erl +++ b/src/crashLog/rumCrashLog.erl @@ -54,9 +54,9 @@ start_link(Filename, MaxFmtSize, MaxFileSize, Date, Count, Rotator) -> init({RelFilename, MaxFmtSize, MaxFileSize, Date, Count, Rotator}) -> Filename = rumUtil:parsePath(RelFilename), case Rotator:openLogFile(Filename, false) of - {ok, Fd, Inode, Ctime, _Size} -> + {ok, Fd, Inode, CTime, _Size} -> scheduleRotation(Date), - {ok, #state{fileName = Filename, fd = Fd, inode = Inode, ctime = Ctime, maxFmtSize = MaxFmtSize, maxFileSize = MaxFileSize, date = Date, count = Count, rotator = Rotator}}; + {ok, #state{fileName = Filename, fd = Fd, inode = Inode, ctime = CTime, maxFmtSize = MaxFmtSize, maxFileSize = MaxFileSize, date = Date, count = Count, rotator = Rotator}}; {error, Reason} -> ?INT_LOG(error, "Failed to open crash log file ~ts with error: ~s", [Filename, file:format_error(Reason)]), {ok, #state{fileName = Filename, maxFmtSize = MaxFmtSize, maxFileSize = MaxFileSize, date = Date, count = Count, flap = true, rotator = Rotator}} @@ -77,7 +77,7 @@ handleInfo({mWriteLog, Event}, State) -> {_, NewState} = writeLog(Event, State), {noreply, NewState}; handleInfo(mRotate, #state{fileName = Name, count = Count, date = Date, rotator = Rotator}) -> - _ = Rotator:rotateLogfile(Name, Count), + _ = Rotator:rotateLogFile(Name, Count), scheduleRotation(Date), kpS; handleInfo(_Msg, _State) -> @@ -164,11 +164,11 @@ writeLog(Event, #state{fileName = FileName, fd = FD, inode = Inode, ctime = Ctim ignore -> {ok, State}; _ -> - case Rotator:ensureLogfile(FileName, FD, Inode, Ctime, false) of + case Rotator:ensureLogFile(FileName, FD, Inode, Ctime, false) of {ok, NewFD, NewInode, NewCtime, FileSize} -> case RotSize > 0 andalso FileSize > RotSize of true -> - _ = Rotator:rotateLogfile(FileName, Count), + _ = Rotator:rotateLogFile(FileName, Count), handleCast({mWriteLog, Event}, State); _ -> TimeBinStr = rumUtil:msToBinStr(), diff --git a/src/eRum.erl b/src/eRum.erl index 4d473a4..0d4273a 100644 --- a/src/eRum.erl +++ b/src/eRum.erl @@ -2,27 +2,55 @@ -include("eRum.hrl"). --define(LAGER_MD_KEY, '__lager_metadata'). --define(TRACE_SINK, '__trace_sink'). --define(ROTATE_TIMEOUT, 100000). - -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. %% API -export([ + %% start stop start/0 + , stop/0 + + %% log and log param , log/3 , log/4 , log/5 , log_unsafe/4 + , do_log/9 + , do_log/10 + , do_log_unsafe/10 + , dispatch_log/5 + , dispatch_log/7 + , dispatch_log/9 + , safe_format/3 + , safe_format_chop/3 + , unsafe_format/2 , md/0 , md/1 + , getLogLevel/1 + , getLogLevel/2 + , setLogLevel/2 + , setLogLevel/3 + , setLogLevel/4 + , getLogLevels/1 + , updateLogevelCfg/1 + , setLogHwm/2 + , setLogHwm/3 + , setLogHwm/4 , rotate_handler/1 , rotate_handler/2 , rotate_sink/1 , rotate_all/0 + , posix_error/1 + + %% stack + , pr/2 + , pr/3 + , pr_stacktrace/1 + , pr_stacktrace/2 + + %% trace , trace/2 , trace/3 , trace_file/2 @@ -41,30 +69,6 @@ , stop_trace/1 , stop_trace/3 , status/0 - , get_loglevel/1 - , get_loglevel/2 - , set_loglevel/2 - , set_loglevel/3 - , set_loglevel/4 - , getLogLevels/1 - , updateLogevelCfg/1 - , posix_error/1 - , set_loghwm/2 - , set_loghwm/3 - , set_loghwm/4 - , safe_format/3 - , safe_format_chop/3 - , unsafe_format/2 - , dispatch_log/5 - , dispatch_log/7 - , dispatch_log/9 - , do_log/9 - , do_log/10 - , do_log_unsafe/10 - , pr/2 - , pr/3 - , pr_stacktrace/1 - , pr_stacktrace/2 ]). -record(trace_func_state_v1, { @@ -76,63 +80,40 @@ started = os:timestamp() :: erlang:timestamp() %% use os:timestamp for compatability }). -%% API +start() -> + application:ensure_all_started(eRum). -%% @doc installs a lager trace handler into the target process (using sys:install) at the specified level. --spec install_trace(pid(), rumAtomLevel()) -> ok. -install_trace(Pid, Level) -> - install_trace(Pid, Level, []). - --spec install_trace(pid(), rumAtomLevel(), [{count, infinity | pos_integer()} | {format_string, string()} | {timeout, timeout()}]) -> ok. -install_trace(Pid, Level, Options) -> - sys:install(Pid, {fun ?MODULE:trace_func/3, trace_state(Pid, Level, Options)}). +stop() -> + application:stop(eRum). -%% @doc remove a previously installed lager trace handler from the target process. --spec remove_trace(pid()) -> ok. -remove_trace(Pid) -> - sys:remove(Pid, fun ?MODULE:trace_func/3). - -%% @doc Start the application. Mainly useful for using `-s lager' as a command -%% line switch to the VM to make lager start on boot. -start() -> start(lager). - -start(App) -> - start_ok(App, application:start(App, permanent)). +%% @doc Manually log a message into lager without using the parse transform. +-spec log(rumAtomLevel(), pid() | atom() | [tuple(), ...], list()) -> ok | {error, lager_not_running}. +log(Level, Pid, Message) when is_pid(Pid); is_atom(Pid) -> + dispatch_log(Level, [{pid, Pid}], Message, [], ?RumDefTruncation); +log(Level, Metadata, Message) when is_list(Metadata) -> + dispatch_log(Level, Metadata, Message, [], ?RumDefTruncation). -start_ok(_App, ok) -> ok; -start_ok(_App1, {error, {already_started, _App2}}) -> ok; -start_ok(App, {error, {not_started, Dep}}) -> - ok = start(Dep), - start(App); -start_ok(App, {error, Reason}) -> - erlang:error({app_start_failed, App, Reason}). +%% @doc Manually log a message into lager without using the parse transform. +-spec log(rumAtomLevel(), pid() | atom() | [tuple(), ...], string(), list()) -> ok | {error, lager_not_running}. +log(Level, Pid, Format, Args) when is_pid(Pid); is_atom(Pid) -> + dispatch_log(Level, [{pid, Pid}], Format, Args, ?RumDefTruncation); +log(Level, Metadata, Format, Args) when is_list(Metadata) -> + dispatch_log(Level, Metadata, Format, Args, ?RumDefTruncation). -%% @doc Get lager metadata for current process --spec md() -> [{atom(), any()}]. -md() -> - case erlang:get(?LAGER_MD_KEY) of - undefined -> []; - MD -> MD - end. +%% @doc Manually log a message into lager without using the parse transform. +-spec log(atom(), rumAtomLevel(), pid() | atom() | [tuple(), ...], string(), list()) -> ok | {error, lager_not_running}. +log(Sink, Level, Pid, Format, Args) when is_pid(Pid); is_atom(Pid) -> + dispatch_log(Sink, Level, [{pid, Pid}], Format, Args, ?RumDefTruncation, safe); +log(Sink, Level, Metadata, Format, Args) when is_list(Metadata) -> + dispatch_log(Sink, Level, Metadata, Format, Args, ?RumDefTruncation, safe). -%% @doc Set lager metadata for current process. -%% Will badarg if you don't supply a list of {key, value} tuples keyed by atoms. --spec md([{atom(), any()}, ...]) -> ok. -md(NewMD) when is_list(NewMD) -> - %% make sure its actually a real proplist - case lists:all( - fun({Key, _Value}) when is_atom(Key) -> true; - (_) -> false - end, NewMD) of - true -> - erlang:put(?LAGER_MD_KEY, NewMD), - ok; - false -> - erlang:error(badarg) - end; -md(_) -> - erlang:error(badarg). +log_unsafe(Level, Metadata, Format, Args) when is_list(Metadata) -> + dispatch_log(?RumDefSink, Level, Metadata, Format, Args, ?RumDefTruncation, unsafe). +%% backwards compatible with beams compiled with lager 2.x +do_log(Severity, Metadata, Format, Args, Size, SeverityAsInt, LevelThreshold, TraceFilters, SinkPid) -> + do_log(Severity, Metadata, Format, Args, Size, SeverityAsInt, + LevelThreshold, TraceFilters, ?RumDefSink, SinkPid). -spec dispatch_log(atom(), rumAtomLevel(), list(), string(), list() | none, pos_integer(), safe | unsafe) -> ok | {error, lager_not_running} | {error, {sink_not_configured, atom()}}. %% this is the same check that the parse transform bakes into the module at compile time @@ -204,40 +185,32 @@ dispatch_log(Severity, _Module, _Function, _Line, _Pid, Metadata, Format, Args, dispatch_log(Severity, Metadata, Format, Args, Size) -> dispatch_log(?RumDefSink, Severity, Metadata, Format, Args, Size, safe). -%% backwards compatible with beams compiled with lager 2.x -do_log(Severity, Metadata, Format, Args, Size, SeverityAsInt, LevelThreshold, TraceFilters, SinkPid) -> - do_log(Severity, Metadata, Format, Args, Size, SeverityAsInt, - LevelThreshold, TraceFilters, ?RumDefSink, SinkPid). - - -%% TODO: -%% Consider making log2/4 that takes the Level, Pid and Message params of log/3 -%% along with a Sink param?? - -%% @doc Manually log a message into lager without using the parse transform. --spec log(rumAtomLevel(), pid() | atom() | [tuple(), ...], list()) -> ok | {error, lager_not_running}. -log(Level, Pid, Message) when is_pid(Pid); is_atom(Pid) -> - dispatch_log(Level, [{pid, Pid}], Message, [], ?RumDefTruncation); -log(Level, Metadata, Message) when is_list(Metadata) -> - dispatch_log(Level, Metadata, Message, [], ?RumDefTruncation). - -%% @doc Manually log a message into lager without using the parse transform. --spec log(rumAtomLevel(), pid() | atom() | [tuple(), ...], string(), list()) -> ok | {error, lager_not_running}. -log(Level, Pid, Format, Args) when is_pid(Pid); is_atom(Pid) -> - dispatch_log(Level, [{pid, Pid}], Format, Args, ?RumDefTruncation); -log(Level, Metadata, Format, Args) when is_list(Metadata) -> - dispatch_log(Level, Metadata, Format, Args, ?RumDefTruncation). - -log_unsafe(Level, Metadata, Format, Args) when is_list(Metadata) -> - dispatch_log(?RumDefSink, Level, Metadata, Format, Args, ?RumDefTruncation, unsafe). +%% @doc Get lager metadata for current process +-spec md() -> [{atom(), any()}]. +md() -> + case erlang:get(?LAGER_MD_KEY) of + undefined -> []; + MD -> MD + end. +%% @doc Set lager metadata for current process. +%% Will badarg if you don't supply a list of {key, value} tuples keyed by atoms. +-spec md([{atom(), any()}, ...]) -> ok. +md(NewMD) when is_list(NewMD) -> + %% make sure its actually a real proplist + case lists:all( + fun({Key, _Value}) when is_atom(Key) -> true; + (_) -> false + end, NewMD) of + true -> + erlang:put(?LAGER_MD_KEY, NewMD), + ok; + false -> + erlang:error(badarg) + end; +md(_) -> + erlang:error(badarg). -%% @doc Manually log a message into lager without using the parse transform. --spec log(atom(), rumAtomLevel(), pid() | atom() | [tuple(), ...], string(), list()) -> ok | {error, lager_not_running}. -log(Sink, Level, Pid, Format, Args) when is_pid(Pid); is_atom(Pid) -> - dispatch_log(Sink, Level, [{pid, Pid}], Format, Args, ?RumDefTruncation, safe); -log(Sink, Level, Metadata, Format, Args) when is_list(Metadata) -> - dispatch_log(Sink, Level, Metadata, Format, Args, ?RumDefTruncation, safe). validate_trace_filters(Filters, Level, Backend) -> Sink = proplists:get_value(sink, Filters, ?RumDefSink), @@ -249,6 +222,117 @@ validate_trace_filters(Filters, Level, Backend) -> }) }. +%% @doc Set the loglevel for a particular backend. +setLogLevel(Handler, Level) when is_atom(Level) -> + setLogLevel(?RumDefSink, Handler, undefined, Level). + +%% @doc Set the loglevel for a particular backend that has multiple identifiers +%% (eg. the file backend). +setLogLevel(Handler, Ident, Level) when is_atom(Level) -> + setLogLevel(?RumDefSink, Handler, Ident, Level). + +%% @doc Set the loglevel for a particular sink's backend that potentially has +%% multiple identifiers. (Use `undefined' if it doesn't have any.) +setLogLevel(Sink, Handler, Ident, Level) when is_atom(Level) -> + HandlerArg = case Ident of + undefined -> Handler; + _ -> {Handler, Ident} + end, + Reply = gen_emm:call(Sink, HandlerArg, {mSetLogLevel, Level}, infinity), + updateLogevelCfg(Sink), + Reply. + + +%% @doc Get the loglevel for a particular backend on the default sink. In the case that the backend has multiple identifiers, the lowest is returned. +getLogLevel(Handler) -> + getLogLevel(?RumDefSink, Handler). + +%% @doc Get the loglevel for a particular sink's backend. In the case that the backend +%% has multiple identifiers, the lowest is returned. +getLogLevel(Sink, Handler) -> + case gen_emm:call(Sink, Handler, mGetLogLevel, infinity) of + Mask when is_integer(Mask) -> + case rumUtil:maskToLevels(Mask) of + [] -> none; + Levels -> hd(Levels) + end; + Y -> Y + end. + +getLogLevels(Sink) -> + [gen_emm:call(Sink, Handler, mGetLogLevel, infinity) || Handler <- gen_emm:which_epm(Sink)]. + +%% @doc Set the loghwm for the default sink. +setLogHwm(Handler, Hwm) when is_integer(Hwm) -> + setLogHwm(?RumDefSink, Handler, Hwm). + +%% @doc Set the loghwm for a particular backend. +setLogHwm(Sink, Handler, Hwm) when is_integer(Hwm) -> + gen_event:call(Sink, Handler, {mSetLogHwm, Hwm}, infinity). + +%% @doc Set the loghwm (log high water mark) for file backends with multiple identifiers +setLogHwm(Sink, Handler, Ident, Hwm) when is_integer(Hwm) -> + gen_event:call(Sink, {Handler, Ident}, {mSetLogHwm, Hwm}, infinity). + +%% @doc Print stacktrace in human readable form +pr_stacktrace(Stacktrace) -> + Stacktrace1 = + case application:get_env(lager, reverse_pretty_stacktrace, true) of + true -> + lists:reverse(Stacktrace); + _ -> + Stacktrace + end, + pr_stacktrace_(Stacktrace1). + +pr_stacktrace_(Stacktrace) -> + Indent = "\n ", + lists:foldl( + fun(Entry, Acc) -> + Acc ++ Indent ++ binary_to_list(rumErrLoggerH:formatMfa(Entry)) + end, + [], + Stacktrace). + +pr_stacktrace(Stacktrace, {Class, Reason}) -> + case application:get_env(lager, reverse_pretty_stacktrace, true) of + true -> + lists:flatten( + pr_stacktrace_(lists:reverse(Stacktrace)) ++ "\n" ++ io_lib:format("~s:~p", [Class, Reason])); + _ -> + lists:flatten( + io_lib:format("~s:~p", [Class, Reason]) ++ pr_stacktrace_(Stacktrace)) + end. + +rotate_sink(Sink) -> + Handlers = rumConfig:global_get(handlers), + RotateHandlers = lists:filtermap( + fun({Handler, _, S}) when S == Sink -> {true, {Handler, Sink}}; + (_) -> false + end, + Handlers), + rotate_handlers(RotateHandlers). + +rotate_all() -> + rotate_handlers(lists:map(fun({H, _, S}) -> {H, S} end, + rumConfig:global_get(handlers))). + + +rotate_handlers(Handlers) -> + [rotate_handler(Handler, Sink) || {Handler, Sink} <- Handlers]. + + +rotate_handler(Handler) -> + Handlers = rumConfig:global_get(handlers), + case lists:keyfind(Handler, 1, Handlers) of + {Handler, _, Sink} -> rotate_handler(Handler, Sink); + false -> ok + end. + +rotate_handler(Handler, Sink) -> + gen_emm:call(Sink, Handler, mRotate, ?ROTATE_TIMEOUT). + + trace_file(File, Filter) -> trace_file(File, Filter, debug, []). @@ -341,7 +425,7 @@ stop_trace_int({_Filter, _Level, Backend} = Trace, Sink) -> _ = rumUtil:trace_filter([element(1, T) || T <- NewTraces]), %MinLevel = minimum_loglevel(get_loglevels() ++ get_trace_levels(NewTraces)), rumConfig:set({Sink, loglevel}, {Level, NewTraces}), - case get_loglevel(Sink, Backend) of + case getLogLevel(Sink, Backend) of none -> %% check no other traces point here case lists:keyfind(Backend, 3, NewTraces) of @@ -358,6 +442,20 @@ stop_trace_int({_Filter, _Level, Backend} = Trace, Sink) -> end, ok. +%% @doc installs a lager trace handler into the target process (using sys:install) at the specified level. +-spec install_trace(pid(), rumAtomLevel()) -> ok. +install_trace(Pid, Level) -> + install_trace(Pid, Level, []). + +-spec install_trace(pid(), rumAtomLevel(), [{count, infinity | pos_integer()} | {format_string, string()} | {timeout, timeout()}]) -> ok. +install_trace(Pid, Level, Options) -> + sys:install(Pid, {fun ?MODULE:trace_func/3, trace_state(Pid, Level, Options)}). + +%% @doc remove a previously installed lager trace handler from the target process. +-spec remove_trace(pid()) -> ok. +remove_trace(Pid) -> + sys:remove(Pid, fun ?MODULE:trace_func/3). + list_all_sinks() -> sets:to_list( lists:foldl(fun({_Watcher, _Handler, Sink}, Set) -> @@ -388,7 +486,7 @@ clear_all_traces() -> rumConfig:global_set(handlers, lists:filter( fun({Handler, _Watcher, Sink}) -> - case get_loglevel(Sink, Handler) of + case getLogLevel(Sink, Handler) of none -> gen_event:delete_handler(Sink, Handler, []), false; @@ -415,7 +513,7 @@ status() -> end, Status = ["Lager status:\n", [begin - Level = get_loglevel(Sink, Handler), + Level = getLogLevel(Sink, Handler), get_sink_handler_status(Sink, Handler, Level) end || {Handler, _Watcher, Sink} <- lists:sort(fun({_, _, S1}, {_, _, S2}) -> S1 =< S2 end, @@ -458,44 +556,6 @@ get_sink_handler_status(Sink, Handler, Level) -> [] end. -%% @doc Set the loglevel for a particular backend. -set_loglevel(Handler, Level) when is_atom(Level) -> - set_loglevel(?RumDefSink, Handler, undefined, Level). - -%% @doc Set the loglevel for a particular backend that has multiple identifiers -%% (eg. the file backend). -set_loglevel(Handler, Ident, Level) when is_atom(Level) -> - set_loglevel(?RumDefSink, Handler, Ident, Level). - -%% @doc Set the loglevel for a particular sink's backend that potentially has -%% multiple identifiers. (Use `undefined' if it doesn't have any.) -set_loglevel(Sink, Handler, Ident, Level) when is_atom(Level) -> - HandlerArg = case Ident of - undefined -> Handler; - _ -> {Handler, Ident} - end, - Reply = gen_emm:call(Sink, HandlerArg, {mSetLogLevel, Level}, infinity), - updateLogevelCfg(Sink), - Reply. - - -%% @doc Get the loglevel for a particular backend on the default sink. In the case that the backend -%% has multiple identifiers, the lowest is returned. -get_loglevel(Handler) -> - get_loglevel(?RumDefSink, Handler). - -%% @doc Get the loglevel for a particular sink's backend. In the case that the backend -%% has multiple identifiers, the lowest is returned. -get_loglevel(Sink, Handler) -> - case gen_emm:call(Sink, Handler, mGetLogLevel, infinity) of - Mask when is_integer(Mask) -> - case rumUtil:maskToLevels(Mask) of - [] -> none; - Levels -> hd(Levels) - end; - Y -> Y - end. - %% @doc Try to convert an atom to a posix error, but fall back on printing the %% term if its not a valid posix error code. posix_error(Error) when is_atom(Error) -> @@ -506,21 +566,6 @@ posix_error(Error) when is_atom(Error) -> posix_error(Error) -> safe_format_chop("~p", [Error], ?RumDefTruncation). -getLogLevels(Sink) -> - [gen_emm:call(Sink, Handler, mGetLogLevel, infinity) || Handler <- gen_emm:which_epm(Sink)]. - -%% @doc Set the loghwm for the default sink. -set_loghwm(Handler, Hwm) when is_integer(Hwm) -> - set_loghwm(?RumDefSink, Handler, Hwm). - -%% @doc Set the loghwm for a particular backend. -set_loghwm(Sink, Handler, Hwm) when is_integer(Hwm) -> - gen_event:call(Sink, Handler, {mSetLogHwm, Hwm}, infinity). - -%% @doc Set the loghwm (log high water mark) for file backends with multiple identifiers -set_loghwm(Sink, Handler, Ident, Hwm) when is_integer(Hwm) -> - gen_event:call(Sink, {Handler, Ident}, {mSetLogHwm, Hwm}, infinity). - %% @private add_trace_to_loglevel_config(Trace, Sink) -> {MinLevel, Traces} = rumConfig:get({Sink, loglevel}), @@ -648,62 +693,6 @@ is_record_known(Record, Module) -> end. -%% @doc Print stacktrace in human readable form -pr_stacktrace(Stacktrace) -> - Stacktrace1 = case application:get_env(lager, reverse_pretty_stacktrace, true) of - true -> - lists:reverse(Stacktrace); - _ -> - Stacktrace - end, - pr_stacktrace_(Stacktrace1). - -pr_stacktrace_(Stacktrace) -> - Indent = "\n ", - lists:foldl( - fun(Entry, Acc) -> - Acc ++ Indent ++ rumErrLoggerH:format_mfa(Entry) - end, - [], - Stacktrace). - -pr_stacktrace(Stacktrace, {Class, Reason}) -> - case application:get_env(lager, reverse_pretty_stacktrace, true) of - true -> - lists:flatten( - pr_stacktrace_(lists:reverse(Stacktrace)) ++ "\n" ++ io_lib:format("~s:~p", [Class, Reason])); - _ -> - lists:flatten( - io_lib:format("~s:~p", [Class, Reason]) ++ pr_stacktrace_(Stacktrace)) - end. - -rotate_sink(Sink) -> - Handlers = rumConfig:global_get(handlers), - RotateHandlers = lists:filtermap( - fun({Handler, _, S}) when S == Sink -> {true, {Handler, Sink}}; - (_) -> false - end, - Handlers), - rotate_handlers(RotateHandlers). - -rotate_all() -> - rotate_handlers(lists:map(fun({H, _, S}) -> {H, S} end, - rumConfig:global_get(handlers))). - - -rotate_handlers(Handlers) -> - [rotate_handler(Handler, Sink) || {Handler, Sink} <- Handlers]. - - -rotate_handler(Handler) -> - Handlers = rumConfig:global_get(handlers), - case lists:keyfind(Handler, 1, Handlers) of - {Handler, _, Sink} -> rotate_handler(Handler, Sink); - false -> ok - end. - -rotate_handler(Handler, Sink) -> - gen_emm:call(Sink, Handler, mRotate, ?ROTATE_TIMEOUT). %% @private trace_func(#trace_func_state_v1{pid = Pid, level = Level, format_string = Fmt} = FuncState, Event, ProcState) -> diff --git a/src/eRum_app.erl b/src/eRum_app.erl index 03a3d44..431410b 100644 --- a/src/eRum_app.erl +++ b/src/eRum_app.erl @@ -5,8 +5,7 @@ -include("eRum.hrl"). -export([ - start/0 - , start/2 + start/2 , stop/1 , doStart/0 , startSink/1 @@ -14,9 +13,6 @@ , startHandler/3 ]). -start() -> - application:ensure_all_started(eRum). - start(_StartType, _StartArgs) -> {ok, Pid} = eRum_sup:start_link(), SavedHandlers = doStart(), diff --git a/src/errLogger/rumErrLoggerH.erl b/src/errLogger/rumErrLoggerH.erl index 6feeb80..8561e3c 100644 --- a/src/errLogger/rumErrLoggerH.erl +++ b/src/errLogger/rumErrLoggerH.erl @@ -9,9 +9,9 @@ -export([ setHighWater/1 - , format_reason/1 - , format_mfa/1 - , format_args/2 + , formatReason/1 + , formatMfa/1 + , formatArgs/2 ]). -export([ @@ -193,7 +193,7 @@ logEvent(Event, #state{sink = Sink, raw = FormatRaw} = State) -> {R, N} end, ?CRASH_LOG(Event), - {Md, Formatted} = format_reason_md(Reason), + {Md, Formatted} = formatReasonMd(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 @@ -210,7 +210,7 @@ logEvent(Event, #state{sink = Sink, raw = FormatRaw} = State) -> {R, N} end, ?CRASH_LOG(Event), - {Md, Formatted} = format_reason_md(Reason), + {Md, Formatted} = formatReasonMd(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 @@ -232,13 +232,13 @@ logEvent(Event, #state{sink = Sink, raw = FormatRaw} = State) -> %% 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), + {Md, Formatted} = formatReasonMd(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), + {Md, Formatted} = formatReasonMd(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]); "** Cowboy handler" ++ _ -> @@ -253,7 +253,7 @@ logEvent(Event, #state{sink = Sink, raw = FormatRaw} = State) -> [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}), + {Md, Formatted} = formatReasonMd({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; @@ -263,19 +263,19 @@ logEvent(Event, #state{sink = Sink, raw = FormatRaw} = State) -> 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}), + {Md, Formatted} = formatReasonMd({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}), + {Md, Formatted} = formatReasonMd({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), + {Md, Formatted} = formatReasonMd(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), + {Md, Formatted} = formatReasonMd(Ret), ?LOGFMT(Sink, error, [{pid, Protocol} | Md], "Ranch listener ~p terminated with result:~s", [Ref, Formatted]) end; "webmachine error" ++ _ -> @@ -290,7 +290,7 @@ logEvent(Event, #state{sink = Sink, raw = FormatRaw} = State) -> _ -> Error end, - {Md, Formatted} = format_reason_md(StackTrace), + {Md, Formatted} = formatReasonMd(StackTrace), ?LOGFMT(Sink, error, [{pid, Pid} | Md], "Webmachine error at path ~p : ~s", [Path, Formatted]) end; _ -> @@ -299,18 +299,18 @@ logEvent(Event, #state{sink = Sink, raw = FormatRaw} = State) -> end; {error_report, _GL, {Pid, std_error, D}} -> ?CRASH_LOG(Event), - ?LOGMSG(Sink, error, Pid, print_silly_list(D)); + ?LOGMSG(Sink, error, Pid, printSillyList(D)); {error_report, _GL, {Pid, supervisor_report, D}} -> ?CRASH_LOG(Event), case lists:sort(D) of [{errorContext, Ctx}, {offender, Off}, {reason, Reason}, {supervisor, Name}] -> - Offender = format_offender(Off), - {Md, Formatted} = format_reason_md(Reason), + Offender = formatOffender(Off), + {Md, Formatted} = formatReasonMd(Reason), ?LOGFMT(Sink, error, [{pid, Pid} | Md], "Supervisor ~w had child ~s exit with reason ~s in context ~w", - [supervisor_name(Name), Offender, Formatted, Ctx]); + [supervisorName(Name), Offender, Formatted, Ctx]); _ -> - ?LOGMSG(Sink, error, Pid, "SUPERVISOR REPORT " ++ print_silly_list(D)) + ?LOGMSG(Sink, error, Pid, <<"SUPERVISOR REPORT ", (printSillyList(D))/binary>>) end; {error_report, _GL, {Pid, crash_report, [Self, Neighbours]}} -> ?CRASH_LOG(Event), @@ -319,7 +319,7 @@ logEvent(Event, #state{sink = Sink, raw = FormatRaw} = State) -> {warning_msg, _GL, {Pid, Fmt, Args}} -> ?LOGFMT(Sink, warning, Pid, Fmt, Args); {warning_report, _GL, {Pid, std_warning, Report}} -> - ?LOGMSG(Sink, warning, Pid, print_silly_list(Report)); + ?LOGMSG(Sink, warning, Pid, printSillyList(Report)); {info_msg, _GL, {Pid, Fmt, Args}} -> ?LOGFMT(Sink, info, Pid, Fmt, Args); {info_report, _GL, {Pid, std_info, D}} when is_list(D) -> @@ -330,12 +330,12 @@ logEvent(Event, #state{sink = Sink, raw = FormatRaw} = State) -> true when Reason == stopped -> no_log; _ -> - {Md, Formatted} = format_reason_md(Reason), + {Md, Formatted} = formatReasonMd(Reason), ?LOGFMT(Sink, info, [{pid, Pid} | Md], "Application ~w exited with reason: ~s", [App, Formatted]) end; _ -> - ?LOGMSG(Sink, info, Pid, print_silly_list(D)) + ?LOGMSG(Sink, info, Pid, printSillyList(D)) end; {info_report, _GL, {Pid, std_info, D}} -> ?LOGFMT(Sink, info, Pid, "~w", [D]); @@ -355,13 +355,13 @@ logEvent(Event, #state{sink = Sink, raw = FormatRaw} = State) -> true -> no_log; _ -> - MFA = format_mfa(get_value(mfargs, Started)), + MFA = formatMfa(get_value(mfargs, Started)), Pid = get_value(pid, Started), ?LOGFMT(Sink, debug, P, "Supervisor ~w started ~s at pid ~w", - [supervisor_name(Name), MFA, Pid]) + [supervisorName(Name), MFA, Pid]) end; _ -> - ?LOGMSG(Sink, info, P, "PROGRESS REPORT " ++ print_silly_list(D)) + ?LOGMSG(Sink, info, P, <<"PROGRESS REPORT ", (printSillyList(D))/binary>>) end; _ -> ?LOGFMT(Sink, warning, self(), "Unexpected error_logger event ~w", [Event]) @@ -393,83 +393,82 @@ format_crash_report(Report, Neighbours) -> end, {Class, Reason, Trace} = get_value(error_info, Report), - {Md, ReasonStr} = format_reason_md({Reason, Trace}), + {Md, ReasonStr} = formatReasonMd({Reason, Trace}), 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) -> +formatOffender(Off) -> case get_value(mfargs, Off) of undefined -> %% supervisor_bridge - io_lib:format("at module ~w at ~w", - [get_value(mod, Off), get_value(pid, Off)]); + eFmt:formatBin(<<"at module ~w at ~w">>, [get_value(mod, Off), get_value(pid, Off)]); MFArgs -> %% regular supervisor {_, MFA} = formatMfaMd(MFArgs), %% In 2014 the error report changed from `name' to %% `id', so try that first. - Name = case get_value(id, Off) of - undefined -> - get_value(name, Off); - Id -> - Id - end, - io_lib:format("~p started with ~s at ~w", - [Name, MFA, get_value(pid, Off)]) + Name = + case get_value(id, Off) of + undefined -> + get_value(name, Off); + Id -> + Id + end, + eFmt:formatBin(<<"at module ~w at ~w">>, [Name, MFA, get_value(pid, Off)]) end. %% backwards compatability shim -format_reason(Reason) -> - element(2, format_reason_md(Reason)). +formatReason(Reason) -> + element(2, formatReasonMd(Reason)). --spec format_reason_md(Stacktrace :: any()) -> {Metadata :: [{atom(), any()}], String :: list()}. -format_reason_md({'function not exported', [{M, F, A}, MFA | _]}) -> +-spec formatReasonMd(Stacktrace :: any()) -> {Metadata :: [{atom(), any()}], String :: list()}. +formatReasonMd({'function not exported', [{M, F, A}, MFA | _]}) -> {Md, Formatted} = formatMfaMd(MFA), {_, Formatted2} = formatMfaMd({M, F, length(A)}), - {[{reason, 'function not exported'} | Md], ["call to undefined function ", Formatted2, " from ", Formatted]}; -format_reason_md({'function not exported', [{M, F, A, _Props}, MFA | _]}) -> + {[{reason, 'function not exported'} | Md], <<"call to undefined function ", Formatted2/binary, " from ", Formatted/binary>>}; +formatReasonMd({'function not exported', [{M, F, A, _Props}, MFA | _]}) -> %% R15 line numbers {Md, Formatted} = formatMfaMd(MFA), {_, Formatted2} = formatMfaMd({M, F, length(A)}), - {[{reason, 'function not exported'} | Md], ["call to undefined function ", Formatted2, " from ", Formatted]}; -format_reason_md({undef, [MFA | _]}) -> + {[{reason, 'function not exported'} | Md], <<"call to undefined function ", Formatted2/binary, " from ", Formatted/binary>>}; +formatReasonMd({undef, [MFA | _]}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{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}}) -> + {[{reason, undef} | Md], <<"call to undefined function ", Formatted/binary>>}; +formatReasonMd({bad_return, {_MFA, {'EXIT', Reason}}}) -> + formatReasonMd(Reason); +formatReasonMd({bad_return, {MFA, Val}}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{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)]}; -format_reason_md({{bad_return_value, Val}, MFA}) -> + {[{reason, bad_return} | Md], <<"bad return value ", (formatVal(Val))/binary, " from ", Formatted/binary>>}; +formatReasonMd({bad_return_value, Val}) -> + {[{reason, bad_return}], <<"bad return value: ", (formatVal(Val))/binary>>}; +formatReasonMd({{bad_return_value, Val}, MFA}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{reason, bad_return_value} | Md], ["bad return value: ", print_val(Val), " in ", Formatted]}; -format_reason_md({{badrecord, Record}, [MFA | _]}) -> + {[{reason, bad_return_value} | Md], <<"bad return value: ", (formatVal(Val))/binary, " in ", Formatted/binary>>}; +formatReasonMd({{badrecord, Record}, [MFA | _]}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{reason, badrecord} | Md], ["bad record ", print_val(Record), " in ", Formatted]}; -format_reason_md({{case_clause, Val}, [MFA | _]}) -> + {[{reason, badrecord} | Md], <<"bad record ", (formatVal(Record))/binary, " in ", Formatted/binary>>}; +formatReasonMd({{case_clause, Val}, [MFA | _]}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{reason, case_clause} | Md], ["no case clause matching ", print_val(Val), " in ", Formatted]}; -format_reason_md({function_clause, [MFA | _]}) -> + {[{reason, case_clause} | Md], <<"no case clause matching ", (formatVal(Val))/binary, " in ", Formatted/binary>>}; +formatReasonMd({function_clause, [MFA | _]}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{reason, function_clause} | Md], ["no function clause matching ", Formatted]}; -format_reason_md({if_clause, [MFA | _]}) -> + {[{reason, function_clause} | Md], <<"no function clause matching ", Formatted/binary>>}; +formatReasonMd({if_clause, [MFA | _]}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{reason, if_clause} | Md], ["no true branch found while evaluating if expression in ", Formatted]}; -format_reason_md({{try_clause, Val}, [MFA | _]}) -> + {[{reason, if_clause} | Md], <<"no true branch found while evaluating if expression in ", Formatted/binary>>}; +formatReasonMd({{try_clause, Val}, [MFA | _]}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{reason, try_clause} | Md], ["no try clause matching ", print_val(Val), " in ", Formatted]}; -format_reason_md({badarith, [MFA | _]}) -> + {[{reason, try_clause} | Md], <<"no try clause matching ", (formatVal(Val))/binary, " in ", Formatted/binary>>}; +formatReasonMd({badarith, [MFA | _]}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{reason, badarith} | Md], ["bad arithmetic expression in ", Formatted]}; -format_reason_md({{badmatch, Val}, [MFA | _]}) -> + {[{reason, badarith} | Md], <<"bad arithmetic expression in ", Formatted/binary>>}; +formatReasonMd({{badmatch, Val}, [MFA | _]}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{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"}; -format_reason_md({system_limit, [{M, F, _} | _] = Trace}) -> + {[{reason, badmatch} | Md], <<"no match of right hand value ", (formatVal(Val))/binary, " in ", Formatted/binary>>}; +formatReasonMd({emfile, _Trace}) -> + {[{reason, emfile}], <<"maximum number of file descriptors exhausted, check ulimit -n">>}; +formatReasonMd({system_limit, [{M, F, _} | _] = Trace}) -> Limit = case {M, F} of {erlang, open_port} -> @@ -485,62 +484,54 @@ format_reason_md({system_limit, [{M, F, _} | _] = Trace}) -> _ -> eFmt:formatBin(<<"~p">>, [Trace], [{charsLimit, 500}]) end, - {[{reason, system_limit}], ["system limit: ", Limit]}; -format_reason_md({badarg, [MFA, MFA2 | _]}) -> + {[{reason, system_limit}], <<"system limit: ", Limit/binary>>}; +formatReasonMd({badarg, [MFA, MFA2 | _]}) -> case MFA of {_M, _F, A, _Props} when is_list(A) -> %% R15 line numbers {Md, Formatted} = formatMfaMd(MFA2), {_, Formatted2} = formatMfaMd(MFA), - {[{reason, badarg} | Md], - ["bad argument in call to ", Formatted2, " in ", Formatted]}; + {[{reason, badarg} | Md], <<"bad argument in call to ", Formatted2, " in ", Formatted/binary>>}; {_M, _F, A} when is_list(A) -> {Md, Formatted} = formatMfaMd(MFA2), {_, Formatted2} = formatMfaMd(MFA), - {[{reason, badarg} | Md], - ["bad argument in call to ", Formatted2, " in ", Formatted]}; + {[{reason, badarg} | Md], <<"bad argument in call to ", Formatted2, " in ", Formatted/binary>>}; _ -> %% seems to be generated by a bad call to a BIF {Md, Formatted} = formatMfaMd(MFA), - {[{reason, badarg} | Md], - ["bad argument in ", Formatted]} + {[{reason, badarg} | Md], <<"bad argument in ", Formatted/binary>>} end; -format_reason_md({{badarg, Stack}, _}) -> - format_reason_md({badarg, Stack}); -format_reason_md({{badarity, {Fun, Args}}, [MFA | _]}) -> +formatReasonMd({{badarg, Stack}, _}) -> + formatReasonMd({badarg, Stack}); +formatReasonMd({{badarity, {Fun, Args}}, [MFA | _]}) -> {arity, Arity} = lists:keyfind(arity, 1, erlang:fun_info(Fun)), {Md, Formatted} = formatMfaMd(MFA), - {[{reason, badarity} | Md], - [io_lib:format("fun called with wrong arity of ~w instead of ~w in ", - [length(Args), Arity]), Formatted]}; -format_reason_md({noproc, MFA}) -> + {[{reason, badarity} | Md], eFmt:formatBin("fun called with wrong arity of ~w instead of ~w in ~s", [length(Args), Arity, Formatted])}; +formatReasonMd({noproc, MFA}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{reason, noproc} | Md], - ["no such process or port in call to ", Formatted]}; -format_reason_md({{badfun, Term}, [MFA | _]}) -> + {[{reason, noproc} | Md], <<"no such process or port in call to ", Formatted/binary>>}; +formatReasonMd({{badfun, Term}, [MFA | _]}) -> {Md, Formatted} = formatMfaMd(MFA), - {[{reason, badfun} | Md], - ["bad function ", print_val(Term), " in ", Formatted]}; -format_reason_md({Reason, [{M, F, A} | _]}) when is_atom(M), is_atom(F), is_integer(A) -> - {Md, Formatted} = format_reason_md(Reason), + {[{reason, badfun} | Md], <<"bad function ", (formatVal(Term))/binary, " in ", Formatted/binary>>}; +formatReasonMd({Reason, [{M, F, A} | _]}) when is_atom(M), is_atom(F), is_integer(A) -> + {Md, Formatted} = formatReasonMd(Reason), {_, Formatted2} = formatMfaMd({M, F, A}), - {Md, [Formatted, " in ", Formatted2]}; -format_reason_md({Reason, [{M, F, A, Props} | _]}) when is_atom(M), is_atom(F), is_integer(A), is_list(Props) -> + {Md, <>}; +formatReasonMd({Reason, [{M, F, A, Props} | _]}) when is_atom(M), is_atom(F), is_integer(A), is_list(Props) -> %% line numbers - {Md, Formatted} = format_reason_md(Reason), + {Md, Formatted} = formatReasonMd(Reason), {_, Formatted2} = formatMfaMd({M, F, A, Props}), - {Md, [Formatted, " in ", Formatted2]}; -format_reason_md(Reason) -> - {Str, _} = rumTruncIo:print(Reason, 500), - {[], Str}. + {Md, <>}; +formatReasonMd(Reason) -> + eFtm:formatBin(<<"~p">>, [Reason], [{charsLimit, 500}]). %% backwards compatability shim -format_mfa(MFA) -> +formatMfa(MFA) -> element(2, formatMfaMd(MFA)). -spec formatMfaMd(any()) -> {[{atom(), any()}], list()}. formatMfaMd({M, F, A}) when is_list(A) -> - ArgsStr = format_args(A, <<>>), + ArgsStr = formatArgs(A, <<>>), {[{module, M}, {function, F}], eFtm:formatBin(<<"~w:~w(", ArgsStr/binary, ")">>, [M, F])}; formatMfaMd({M, F, A}) when is_integer(A) -> {[{module, M}, {function, F}], eFtm:formatBin(<<"~w:~w/~w">>, [M, F, A])}; @@ -563,38 +554,20 @@ formatMfaMd([{M, F, A, Props} | _]) when is_list(Props) -> formatMfaMd(Other) -> {[], eFtm:formatBin(<<"~w">>, [Other])}. -format_args([], ArgsAcc) -> +formatArgs([], ArgsAcc) -> ArgsAcc; -format_args([H], ArgsAcc) -> +formatArgs([H], ArgsAcc) -> Str = eFmt:formatBin(<<"~p">>, [H], [{charsLimit, 100}]), <>; -format_args([H | T], ArgsAcc) -> +formatArgs([H | T], ArgsAcc) -> Str = eFmt:formatBin(<<"~p">>, [H], [{charsLimit, 100}]), - format_args(T, <>). + formatArgs(T, <>). -print_silly_list(L) when is_list(L) -> - case rumStdlib:string_p(L) of - true -> - rumTruncIo:format("~s", [L], ?RumDefTruncation); - _ -> - print_silly_list(L, [], []) - end; -print_silly_list(L) -> - {Str, _} = rumTruncIo:print(L, ?RumDefTruncation), - Str. - -print_silly_list([], Fmt, Acc) -> - rumTruncIo:format(string:join(lists:reverse(Fmt), ", "), - lists:reverse(Acc), ?RumDefTruncation); -print_silly_list([{K, V} | T], Fmt, Acc) -> - print_silly_list(T, ["~p: ~p" | Fmt], [V, K | Acc]); -print_silly_list([H | T], Fmt, Acc) -> - print_silly_list(T, ["~p" | Fmt], [H | Acc]). - -print_val(Val) -> - {Str, _} = rumTruncIo:print(Val, 500), - Str. +formatVal(Val) -> + eFmt:formatBin(<<"~p">>, [Val], [{charsLimit, 500}]). +printSillyList(L) -> + eFmt:formatBin(<<"~p">>, [L], [{charsLimit, ?RumDefTruncation}]). %% @doc Faster than proplists, but with the same API as long as you don't need to %% handle bare atom keys @@ -607,8 +580,8 @@ get_value(Key, List, Default) -> {Key, Value} -> Value end. -supervisor_name({local, Name}) -> Name; -supervisor_name(Name) -> Name. +supervisorName({local, Name}) -> Name; +supervisorName(Name) -> Name. -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). diff --git a/src/mgrKiller/rumMgrKiller.erl b/src/mgrKiller/rumMgrKiller.erl index 3d2bfb3..db826a9 100644 --- a/src/mgrKiller/rumMgrKiller.erl +++ b/src/mgrKiller/rumMgrKiller.erl @@ -1,12 +1,19 @@ -module(rumMgrKiller). --behavior(gen_event). +-behavior(gen_emm). --export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]). +-include("eRum.hrl"). -export([kill_me/0]). --include("eRum.hrl"). +-export([ + init/1 + , handleEvent/2 + , handleCall/2 + , handleInfo/2 + , terminate/2 + , code_change/3 +]). -record(state, { killerHwm :: non_neg_integer(), @@ -14,25 +21,24 @@ }). kill_me() -> - gen_emm:call(rumEvent, ?MODULE, kill_self). + gen_emm:call(rumEvent, ?MODULE, mKillSelf). init([KillerHWM, KillerReinstallAfter]) -> {ok, #state{killerHwm = KillerHWM, killerReTime = KillerReinstallAfter}}. -handle_call(mGetLogLevel, State) -> - {ok, ?LOG_NONE, State}; -handle_call({mSetLogLevel, _Level}, State) -> - {ok, ok, State}; -handle_call(get_settings, State = #state{killerHwm = KillerHWM, killerReTime = KillerReinstallAfter}) -> - {ok, [KillerHWM, KillerReinstallAfter], State}; -handle_call(kill_self, #state{killerHwm = KillerHWM, killerReTime = KillerReinstallAfter}) -> +handleCall(mGetLogLevel, State) -> + {replay, ?LOG_NONE, State}; +handleCall({mSetLogLevel, _Level}, State) -> + {replay, ok, State}; +handleCall(mGetSettings, State = #state{killerHwm = KillerHWM, killerReTime = KillerReinstallAfter}) -> + {replay, [KillerHWM, KillerReinstallAfter], State}; +handleCall(mKillSelf, #state{killerHwm = KillerHWM, killerReTime = KillerReinstallAfter}) -> exit({kill_me, [KillerHWM, KillerReinstallAfter]}); -handle_call(_Request, State) -> - {ok, ok, State}. -%% It's not the best idea in the world to check the queue length for every -%% log message. We can make this operation work on a poll timer in the -%% future. -handle_event({mWriteLog, _Message}, State = #state{killerHwm = KillerHWM, killerReTime = KillerReinstallAfter}) -> +handleCall(_Request, State) -> + {replay, ok, State}. + +%% 检查每个日志消息的队列长度不是世界上最好的主意。我们将来可以使此操作在轮询计时器上起作用。 +handleEvent({mWriteLog, _Message}, State = #state{killerHwm = KillerHWM, killerReTime = KillerReinstallAfter}) -> {message_queue_len, Len} = process_info(self(), message_queue_len), case Len > KillerHWM of true -> @@ -40,10 +46,10 @@ handle_event({mWriteLog, _Message}, State = #state{killerHwm = KillerHWM, killer _ -> {ok, State} end; -handle_event(_Event, State) -> +handleEvent(_Event, State) -> {ok, State}. -handle_info(_Info, State) -> +handleInfo(_Info, State) -> {ok, State}. terminate(_Reason, _State) -> diff --git a/src/rotator/rumRotatorIns.erl b/src/rotator/rumRotatorIns.erl index 02ad417..0359571 100644 --- a/src/rotator/rumRotatorIns.erl +++ b/src/rotator/rumRotatorIns.erl @@ -49,13 +49,13 @@ ensureLogFile(FileName, Fd, Inode, CTime, Buffer) -> _ -> case rumUtil:isFileChanged(FileName, Inode, CTime) of {true, _FInfo} -> - reopenLogfile(FileName, Fd, Buffer); + reopenLogFile(FileName, Fd, Buffer); {_, FInfo} -> {ok, Fd, Inode, CTime, FInfo#file_info.size} end end. -reopenLogfile(FileName, Fd, Buffer) -> +reopenLogFile(FileName, Fd, Buffer) -> %% Flush and close any file handles. delayed write can cause file:close not to do a close _ = file:datasync(Fd), _ = file:close(Fd), diff --git a/src/utils/rumStdlib.erl b/src/utils/rumStdlib.erl index 44a913c..a10bc2e 100644 --- a/src/utils/rumStdlib.erl +++ b/src/utils/rumStdlib.erl @@ -1,95 +1,12 @@ -module(rumStdlib). --export([string_p/1]). --export([write_time/2, maybe_utc/1]). --export([isErrorReport/1, is_my_info_report/1]). +-export([ + isErrorReport/1, + is_my_info_report/1 +]). -export([sup_get/2]). -export([proc_lib_format/2]). - -%% from error_logger_file_h -string_p([]) -> - false; -string_p(Term) -> - string_p1(Term). - -string_p1([H | T]) when is_integer(H), H >= $\s, H < 256 -> - string_p1(T); -string_p1([$\n | T]) -> string_p1(T); -string_p1([$\r | T]) -> string_p1(T); -string_p1([$\t | T]) -> string_p1(T); -string_p1([$\v | T]) -> string_p1(T); -string_p1([$\b | T]) -> string_p1(T); -string_p1([$\f | T]) -> string_p1(T); -string_p1([$\e | T]) -> string_p1(T); -string_p1([H | T]) when is_list(H) -> - case string_p1(H) of - true -> string_p1(T); - _ -> false - end; -string_p1([]) -> true; -string_p1(_) -> false. - -%% From calendar --type year1970() :: 1970..10000. % should probably be 1970.. --type month() :: 1..12. --type day() :: 1..31. --type hour() :: 0..23. --type minute() :: 0..59. --type second() :: 0..59. --type t_time() :: {hour(), minute(), second()}. --type t_datetime1970() :: {{year1970(), month(), day()}, t_time()}. - -%% From OTP stdlib's error_logger_tty_h.erl ... These functions aren't -%% exported. --spec write_time({utc, t_datetime1970()} | t_datetime1970(), string()) -> string(). -write_time({utc, {{Y, Mo, D}, {H, Mi, S}}}, Type) -> - io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n", - [Type, D, month(Mo), Y, t(H), t(Mi), t(S)]); -write_time({{Y, Mo, D}, {H, Mi, S}}, Type) -> - io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n", - [Type, D, month(Mo), Y, t(H), t(Mi), t(S)]). - --spec maybe_utc(t_datetime1970()) -> {utc, t_datetime1970()} | t_datetime1970(). -maybe_utc(Time) -> - UTC = case application:get_env(sasl, utc_log) of - {ok, Val} -> - Val; - undefined -> - %% Backwards compatible: - application:get_env(stdlib, utc_log, false) - end, - if - UTC =:= true -> - UTCTime = case calendar:local_time_to_universal_time_dst(Time) of - [] -> calendar:local_time(); - [T0 | _] -> T0 - end, - {utc, UTCTime}; - true -> - Time - end. - -t(X) when is_integer(X) -> - t1(integer_to_list(X)); -t(_) -> - "". -t1([X]) -> [$0, X]; -t1(X) -> X. - -month(1) -> "Jan"; -month(2) -> "Feb"; -month(3) -> "Mar"; -month(4) -> "Apr"; -month(5) -> "May"; -month(6) -> "Jun"; -month(7) -> "Jul"; -month(8) -> "Aug"; -month(9) -> "Sep"; -month(10) -> "Oct"; -month(11) -> "Nov"; -month(12) -> "Dec". - %% From OTP sasl's sasl_report.erl ... These functions aren't %% exported. -spec isErrorReport(atom()) -> boolean(). diff --git a/src/utils/rumUtil.erl b/src/utils/rumUtil.erl index 742b3bb..6f2eeca 100644 --- a/src/utils/rumUtil.erl +++ b/src/utils/rumUtil.erl @@ -8,6 +8,7 @@ , levelToNum/1 , levelToChr/1 , numToLevel/1 + , validateLogLevel/1 , configToMask/1 , atomCfgToLevels/1 , maskToLevels/1 @@ -81,7 +82,17 @@ levelToChr(alert) -> $A; levelToChr(emergency) -> $M; levelToChr(none) -> $ . --spec configToMask(atom()|string()) -> integer(). +-spec validateLogLevel(atom()|string()) -> false | rumMaskLevel(). +validateLogLevel(Level) -> + try rumUtil:configToMask(Level) of + Levels -> + Levels + catch + _:_ -> + false + end. + +-spec configToMask(atom()|string()) -> rumMaskLevel(). configToMask(Conf) -> Levels = atomCfgToLevels(Conf), levelsToMask(Levels, 0). diff --git a/src/watcher/rumHWatcherSrv.erl b/src/watcher/rumHWatcherSrv.erl index f52ba0c..0345bfb 100644 --- a/src/watcher/rumHWatcherSrv.erl +++ b/src/watcher/rumHWatcherSrv.erl @@ -61,7 +61,7 @@ handleInfo({gen_event_EXIT, Module, {'EXIT', {kill_me, [_KillerHWM, KillerReinst _ = timer:apply_after(KillerReinstallAfter, lager_app, start_handler, [Sink, Module, Config]), {stop, normal, State}; handleInfo({gen_event_EXIT, Module, Reason}, #state{module = Module, config = Config, sink = Sink} = State) -> - case eRum:log(error, self(), "Lager event handler ~p exited with reason ~s", [Module, rumErrLoggerH:format_reason(Reason)]) of + case eRum:log(error, self(), "Lager event handler ~p exited with reason ~s", [Module, rumErrLoggerH:formatReason(Reason)]) of ok -> installHandler(Module, Config, Sink); {error, _} ->