Преглед на файлове

ft: 代码整理

master
SisMaker преди 4 години
родител
ревизия
d85a0f3093
променени са 14 файла, в които са добавени 462 реда и са изтрити 582 реда
  1. +4
    -4
      README.md
  2. +1
    -1
      eRum.sample.config
  3. +28
    -0
      include/eRum.hrl
  4. +42
    -48
      src/backend/rumBkdConsole.erl
  5. +23
    -57
      src/backend/rumBkdFile.erl
  6. +5
    -5
      src/crashLog/rumCrashLog.erl
  7. +212
    -223
      src/eRum.erl
  8. +1
    -5
      src/eRum_app.erl
  9. +102
    -129
      src/errLogger/rumErrLoggerH.erl
  10. +25
    -19
      src/mgrKiller/rumMgrKiller.erl
  11. +2
    -2
      src/rotator/rumRotatorIns.erl
  12. +4
    -87
      src/utils/rumStdlib.erl
  13. +12
    -1
      src/utils/rumUtil.erl
  14. +1
    -1
      src/watcher/rumHWatcherSrv.erl

+ 4
- 4
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).
```

+ 1
- 1
eRum.sample.config Целия файл

@ -16,7 +16,7 @@
]},
%% ******************************************** format相关 ******************************************************
{metadata_whitelist, []]},
{metadata_whitelist, []},
{reverse_pretty_stacktrace, true},
%%*********************************************** 异步日志相关 *****************************************************

+ 28
- 0
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

+ 42
- 48
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
}

+ 23
- 57
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() ->

+ 5
- 5
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(),

+ 212
- 223
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) ->

+ 1
- 5
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(),

+ 102
- 129
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,
class="nn">eFmt class="p">: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, <<Formatted/binary, " in ", Formatted2/binary>>};
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, <<Formatted/binary, " in ", Formatted2/binary>>};
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}]),
<<ArgsAcc/binary, Str/binary>>;
format_args([H | T], ArgsAcc) ->
formatArgs([H | T], ArgsAcc) ->
Str = eFmt:formatBin(<<"~p">>, [H], [{charsLimit, 100}]),
format_args(T, <<ArgsAcc/binary, Str/binary, ",">>).
formatArgs(T, <<ArgsAcc/binary, Str/binary, ",">>).
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").

+ 25
- 19
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) ->

+ 2
- 2
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),

+ 4
- 87
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().

+ 12
- 1
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).

+ 1
- 1
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, _} ->

Зареждане…
Отказ
Запис