diff --git a/include/eRum.hrl b/include/eRum.hrl index 0e3d2ec..46a7a15 100644 --- a/include/eRum.hrl +++ b/include/eRum.hrl @@ -19,9 +19,9 @@ %% 默认日志文件选项 -define(RumDefHandler, [ - {rumBackendConsole, [{level, info}]}, - {rumBackendFile, [{file, "error.log"}, {level, error}, {size, 10485760}, {date, "$D0"}, {count, 5}]}, - {rumBackendFile, [{file, "console.log"}, {level, info}, {size, 10485760}, {date, "$D0"}, {count, 5}]} + {rumBkdConsole, [{level, info}]}, + {rumBkdFile, [{file, "error.log"}, {level, error}, {size, 10485760}, {date, "$D0"}, {count, 5}]}, + {rumBkdFile, [{file, "console.log"}, {level, info}, {size, 10485760}, {date, "$D0"}, {count, 5}]} ]). %% 获取元数据的宏定义 diff --git a/src/backend/rumBkdConsole.erl b/src/backend/rumBkdConsole.erl index 0fd19a5..36dcf9e 100644 --- a/src/backend/rumBkdConsole.erl +++ b/src/backend/rumBkdConsole.erl @@ -1,77 +1,47 @@ -%% @doc Console backend for lager. +-module(rumBkdConsole). %% Configuration is a proplist with the following keys: -%% +%%`level' - log level to use +%%`use_stderr' - either `true' or `false', defaults to false. If set to true, use standard error to output console log messages +%%`formatter' - the module to use when formatting log messages. Defaults to `rumFormatter' +%%`formatter_config' - the format configuration string. Defaults to `time [ severity ] message' --module(rumBkdConsole). +-behaviour(gen_emm). + +-include("eRum.hrl"). --behaviour(gen_event). +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). +-compile([{parse_transform, rumTransform}]). +-endif. + + +-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}]). -export([ init/1 - , handle_call/2 - , handle_event/2 - , handle_info/2 + , handleCall/2 + , handleEvent/2 + , handleInfo/2 , terminate/2 , code_change/3 ]). --record(state, {level :: {'mask', integer()}, +-record(state, { + level :: {'mask', integer()}, out = user :: user | standard_error | pid(), id :: atom() | {atom(), any()}, formatter :: atom(), format_config :: any(), - colors = [] :: list()}). - --ifdef(TEST). --include_lib("eunit/include/eunit.hrl"). --compile([{parse_transform, lager_transform}]). --endif. - - --include("eRum.hrl"). - --define(TERSE_FORMAT, [time, " ", color, "[", severity, "] ", message]). --define(DEFAULT_FORMAT_CONFIG, ?TERSE_FORMAT ++ [eol()]). --define(FORMAT_CONFIG_OFF, [{eol, eol()}]). - --ifdef(TEST). --define(DEPRECATED(_Msg), ok). --else. --define(DEPRECATED(Msg), - io:format(user, "WARNING: This is a deprecated console configuration. Please use \"~w\" instead.~n", [Msg])). --endif. - -%% @private -init([Level]) when is_atom(Level) -> - ?DEPRECATED([{level, Level}]), - init([{level, Level}]); -init([Level, true]) when is_atom(Level) -> % for backwards compatibility - ?DEPRECATED([{level, Level}, {formatter_config, [{eol, "\\r\\n\\"}]}]), - init([{level, Level}, {formatter_config, ?FORMAT_CONFIG_OFF}]); -init([Level, false]) when is_atom(Level) -> % for backwards compatibility - ?DEPRECATED([{level, Level}]), - init([{level, Level}]); + colors = [] :: list() +}). -init(Options) when is_list(Options) -> - true = validate_options(Options), - Colors = case application:get_env(lager, colored) of - {ok, true} -> - {ok, LagerColors} = application:get_env(lager, colors), - LagerColors; - _ -> [] - end, - Level = get_option(level, Options, undefined), - try {is_new_style_console_available(), rumUtil:config_to_mask(Level)} of - {false, _} -> +init(Opts) -> + 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 @@ -83,74 +53,37 @@ init(Options) when is_list(Options) -> io:format("WARNING: " ++ Msg ++ "~n"), ?INT_LOG(warning, Msg, []), {error, {fatal, old_shell}}; - {true, L} -> - [UseErr, GroupLeader, ID, Formatter, Config] = [get_option(K, Options, Default) || {K, Default} <- [ - {use_stderr, false}, - {group_leader, false}, - {id, ?MODULE}, - {formatter, lager_default_formatter}, - {formatter_config, ?DEFAULT_FORMAT_CONFIG} - ] - ], - Out = case UseErr of - false -> - case GroupLeader of - false -> user; - GLPid when is_pid(GLPid) -> - erlang:monitor(process, GLPid), - GLPid - end; - true -> standard_error - end, - {ok, #state{level = L, - id = ID, - out = Out, - formatter = Formatter, - format_config = Config, - colors = Colors}} - catch - _:_ -> - {error, {fatal, bad_log_level}} - end; -init(Level) when is_atom(Level) -> - ?DEPRECATED([{level, Level}]), - init([{level, Level}]); -init(Other) -> - {error, {fatal, {bad_console_config, Other}}}. + _ -> + true = checkOpts(Opts), + Colors = ?IIF(rumUtil:get_env(colored, false), rumUtil:get_env(colors, []), []), + Level = rumUtil:get_opt(level, Opts, undefined), + L = rumUtil:config_to_mask(Level), + [UseErr, GroupLeader, ID, Formatter, Config] = [rumUtil:get_opt(Key, Opts, Def) || {Key, Def} <- ?DefOpts], + Out = ?IIF(UseErr, standard_error, ?IIF(GroupLeader == false, user, begin erlang:monitor(process, GroupLeader), GroupLeader end)), + {ok, #state{level = L, id = ID, out = Out, formatter = Formatter, format_config = Config, colors = Colors}} + end. -validate_options([]) -> true; -validate_options([{level, L} | T]) when is_atom(L) -> - case lists:member(L, ?RumLevels) of - false -> - throw({error, {fatal, {bad_level, L}}}); - true -> - validate_options(T) - end; -validate_options([{use_stderr, true} | T]) -> - validate_options(T); -validate_options([{use_stderr, false} | T]) -> - validate_options(T); -validate_options([{formatter, M} | T]) when is_atom(M) -> - validate_options(T); -validate_options([{formatter_config, C} | T]) when is_list(C) -> - validate_options(T); -validate_options([{group_leader, L} | T]) when is_pid(L) -> - validate_options(T); -validate_options([{id, {?MODULE, _}} | T]) -> - validate_options(T); -validate_options([H | _]) -> +checkOpts([]) -> true; +checkOpts([{level, L} | T]) when is_atom(L) -> + ?IIF(lists:member(L, ?RumLevels) == false, throw({error, {fatal, {bad_level, L}}}), checkOpts(T)); +checkOpts([{use_stderr, true} | T]) -> + checkOpts(T); +checkOpts([{use_stderr, false} | T]) -> + checkOpts(T); +checkOpts([{formatter, M} | T]) when is_atom(M) -> + checkOpts(T); +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 | _]) -> throw({error, {fatal, {bad_console_config, H}}}). -get_option(K, Options, Default) -> - case lists:keyfind(K, 1, Options) of - {K, V} -> V; - false -> Default - end. - -%% @private -handle_call(get_loglevel, #state{level = Level} = State) -> +handleCall(mGetLogLevel, #state{level = Level} = State) -> {ok, Level, State}; -handle_call({set_loglevel, Level}, State) -> +handleCall({mSetLogLevel, Level}, State) -> try rumUtil:config_to_mask(Level) of Levels -> {ok, ok, State#state{level = Levels}} @@ -158,11 +91,11 @@ handle_call({set_loglevel, Level}, State) -> _:_ -> {ok, {error, bad_log_level}, State} end; -handle_call(_Request, State) -> +handleCall(_Request, State) -> {ok, ok, State}. %% @private -handle_event({mWriteLog, Message}, +handleEvent({mWriteLog, Message}, #state{level = L, out = Out, formatter = Formatter, format_config = FormatConfig, colors = Colors, id = ID} = State) -> case rumUtil:is_loggable(Message, L, ID) of true -> @@ -171,16 +104,14 @@ handle_event({mWriteLog, Message}, false -> {ok, State} end; -handle_event(_Event, State) -> +handleEvent(_Event, State) -> {ok, State}. -%% @private -handle_info({'DOWN', _, process, Out, _}, #state{out = Out}) -> +handleInfo({'DOWN', _, process, Out, _}, #state{out = Out}) -> remove_handler; -handle_info(_Info, State) -> +handleInfo(_Info, State) -> {ok, State}. -%% @private terminate(remove_handler, _State = #state{id = ID}) -> %% have to do this asynchronously because we're in the event handlr spawn(fun() -> eRum:clear_trace_by_destination(ID) end), @@ -188,7 +119,6 @@ terminate(remove_handler, _State = #state{id = ID}) -> terminate(_Reason, _State) -> ok. -%% @private code_change(_OldVsn, State, _Extra) -> {ok, State}. @@ -200,11 +130,7 @@ eol() -> "\r\n" end. --ifdef(TEST). -is_new_style_console_available() -> - true. --else. -is_new_style_console_available() -> +isNewStyleConsole() -> %% Criteria: %% 1. If the user has specified '-noshell' on the command line, %% then we will pretend that the new-style console is available. @@ -215,10 +141,7 @@ is_new_style_console_available() -> %% 3. If the user_drv process is registered, all is OK. %% 'user_drv' is a registered proc name used by the "new" %% console driver. - init:get_argument(noshell) /= error orelse - element(1, os:type()) /= win32 orelse - is_pid(whereis(user_drv)). --endif. + init:get_argument(noshell) /= error orelse element(1, os:type()) /= win32 orelse is_pid(whereis(user_drv)). -ifdef(TEST). console_config_validation_test_() -> @@ -229,10 +152,10 @@ console_config_validation_test_() -> {formatter_config, ["blort", "garbage"]}, {use_stderr, false}], [ - ?_assertEqual(true, validate_options(Good)), - ?_assertThrow({error, {fatal, {bad_level, foo}}}, validate_options(Bad1)), - ?_assertThrow({error, {fatal, {bad_console_config, {use_stderr, flase}}}}, validate_options(Bad2)), - ?_assertEqual(true, validate_options(AllGood)) + ?_assertEqual(true, checkOpts(Good)), + ?_assertThrow({error, {fatal, {bad_level, foo}}}, checkOpts(Bad1)), + ?_assertThrow({error, {fatal, {bad_console_config, {use_stderr, flase}}}}, checkOpts(Bad2)), + ?_assertEqual(true, checkOpts(AllGood)) ]. console_log_test_() -> diff --git a/src/backend/rumBkdFile.erl b/src/backend/rumBkdFile.erl index 7bb4903..7f644d2 100644 --- a/src/backend/rumBkdFile.erl +++ b/src/backend/rumBkdFile.erl @@ -115,7 +115,7 @@ init(LogFileConfig) when is_list(LogFileConfig) -> end. %% @private -handle_call({set_loglevel, Level}, #state{name = Ident} = State) -> +handle_call({mSetLogLevel, Level}, #state{name = Ident} = State) -> case validate_loglevel(Level) of false -> {ok, {error, bad_loglevel}, State}; @@ -123,7 +123,7 @@ handle_call({set_loglevel, Level}, #state{name = Ident} = State) -> ?INT_LOG(notice, "Changed loglevel of ~s to ~p", [Ident, Level]), {ok, ok, State#state{level = Levels}} end; -handle_call(get_loglevel, #state{level = Level} = State) -> +handle_call(mGetLogLevel, #state{level = Level} = State) -> {ok, Level, State}; handle_call({set_loghwm, Hwm}, #state{shaper = Shaper, name = Name} = State) -> case validate_logfile_proplist([{file, Name}, {high_water_mark, Hwm}]) of @@ -462,10 +462,10 @@ close_file(#state{fd = FD} = State) -> -ifdef(TEST). get_loglevel_test() -> - {ok, Level, _} = handle_call(get_loglevel, + {ok, Level, _} = handle_call(mGetLogLevel, #state{name = "bar", level = rumUtil:config_to_mask(info), fd = 0, inode = 0, ctime = undefined}), ?assertEqual(Level, rumUtil:config_to_mask(info)), - {ok, Level2, _} = handle_call(get_loglevel, + {ok, Level2, _} = handle_call(mGetLogLevel, #state{name = "foo", level = rumUtil:config_to_mask(warning), fd = 0, inode = 0, ctime = undefined}), ?assertEqual(Level2, rumUtil:config_to_mask(warning)). diff --git a/src/backend/rumBkdThrottle.erl b/src/backend/rumBkdThrottle.erl index b0f5b0a..db1a728 100644 --- a/src/backend/rumBkdThrottle.erl +++ b/src/backend/rumBkdThrottle.erl @@ -30,9 +30,9 @@ init([{sink, Sink}, Hwm, Window]) -> rumConfig:set({Sink, async}, true), {ok, #state{sink = Sink, hwm = Hwm, window_min = Hwm - Window}}. -handle_call(get_loglevel, State) -> +handle_call(mGetLogLevel, State) -> {ok, {mask, ?LOG_NONE}, State}; -handle_call({set_loglevel, _Level}, State) -> +handle_call({mSetLogLevel, _Level}, State) -> {ok, ok, State}; handle_call(_Request, State) -> {ok, ok, State}. diff --git a/src/eRum.erl b/src/eRum.erl index dbc2da7..b2a7b90 100644 --- a/src/eRum.erl +++ b/src/eRum.erl @@ -477,7 +477,7 @@ set_loglevel(Sink, Handler, Ident, Level) when is_atom(Level) -> undefined -> Handler; _ -> {Handler, Ident} end, - Reply = gen_event:call(Sink, HandlerArg, {set_loglevel, Level}, infinity), + Reply = gen_event:call(Sink, HandlerArg, {mSetLogLevel, Level}, infinity), updateLogevelCfg(Sink), Reply. @@ -490,7 +490,7 @@ get_loglevel(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_event:call(Sink, Handler, get_loglevel, infinity) of + case gen_event:call(Sink, Handler, mGetLogLevel, infinity) of {mask, Mask} -> case rumUtil:maskToLevels(Mask) of [] -> none; @@ -513,7 +513,7 @@ posix_error(Error) -> %% @private get_loglevels(Sink) -> - [gen_event:call(Sink, Handler, get_loglevel, infinity) || + [gen_event:call(Sink, Handler, mGetLogLevel, infinity) || Handler <- gen_event:which_handlers(Sink)]. %% @doc Set the loghwm for the default sink. diff --git a/src/mgrKiller/rumMgrKiller.erl b/src/mgrKiller/rumMgrKiller.erl index d1849d6..b7d0acc 100644 --- a/src/mgrKiller/rumMgrKiller.erl +++ b/src/mgrKiller/rumMgrKiller.erl @@ -19,9 +19,9 @@ kill_me() -> init([KillerHWM, KillerReinstallAfter]) -> {ok, #state{killerHwm = KillerHWM, killerReTime = KillerReinstallAfter}}. -handle_call(get_loglevel, State) -> +handle_call(mGetLogLevel, State) -> {ok, {mask, ?LOG_NONE}, State}; -handle_call({set_loglevel, _Level}, State) -> +handle_call({mSetLogLevel, _Level}, State) -> {ok, ok, State}; handle_call(get_settings, State = #state{killerHwm = KillerHWM, killerReTime = KillerReinstallAfter}) -> {ok, [KillerHWM, KillerReinstallAfter], State}; diff --git a/src/test/lager_common_test_backend.erl b/src/test/lager_common_test_backend.erl index a1cb1c3..9afef64 100644 --- a/src/test/lager_common_test_backend.erl +++ b/src/test/lager_common_test_backend.erl @@ -89,9 +89,9 @@ handle_event(Event, State) -> -spec(handle_call(any(), #state{}) -> {ok, any(), #state{}}). %% @private %% @doc gets and sets loglevel. This is part of the lager backend api. -handle_call(get_loglevel, #state{level = Level} = State) -> +handle_call(mGetLogLevel, #state{level = Level} = State) -> {ok, Level, State}; -handle_call({set_loglevel, Level}, State) -> +handle_call({mSetLogLevel, Level}, State) -> case lists:member(Level, ?RumLevels) of true -> {ok, ok, State#state{level = rumUtil:config_to_mask(Level)}}; diff --git a/src/utils/rumUtil.erl b/src/utils/rumUtil.erl index 5e0dd8f..05e79a0 100644 --- a/src/utils/rumUtil.erl +++ b/src/utils/rumUtil.erl @@ -31,6 +31,7 @@ , maybe_flush/2 , isFileChanged/3 , get_env/2 + , get_opt/3 ]). -ifdef(TEST). @@ -633,6 +634,14 @@ get_env(Key, Def) -> Def end. +get_opt(Key, Opts, Def) -> + case lists:keyfind(Key, 1, Opts) of + false -> + Def; + V -> + element(2, V) + end. + -ifdef(TEST). parse_test() -> ?assertEqual({ok, {undefined, undefined, 0, undefined}}, rumUtil:parseRotateSpec("$H0")), diff --git a/test/lager_slow_backend.erl b/test/lager_slow_backend.erl index 0a2f277..cd87dc3 100644 --- a/test/lager_slow_backend.erl +++ b/test/lager_slow_backend.erl @@ -13,7 +13,7 @@ init([{delay, Delay}]) -> {ok, #state{delay = Delay}}. -handle_call(get_loglevel, State) -> +handle_call(mGetLogLevel, State) -> {ok, rumUtil:config_to_mask(debug), State}; handle_call(_Request, State) -> {ok, ok, State}. diff --git a/test/lager_test_backend.erl b/test/lager_test_backend.erl index 11dc7a6..9cdd7a9 100644 --- a/test/lager_test_backend.erl +++ b/test/lager_test_backend.erl @@ -81,9 +81,9 @@ handle_call(pop_ignored, #state{ignored = Ignored} = State) -> end; handle_call(get_buffer, #state{buffer = Buffer} = State) -> {ok, Buffer, State}; -handle_call(get_loglevel, #state{level = Level} = State) -> +handle_call(mGetLogLevel, #state{level = Level} = State) -> {ok, Level, State}; -handle_call({set_loglevel, Level}, State) -> +handle_call({mSetLogLevel, Level}, State) -> {ok, ok, State#state{level = lager_util:config_to_mask(Level)}}; handle_call(print_state, State) -> spawn(fun() -> lager:info("State ~p", [lager:pr(State, ?MODULE)]) end),