diff --git a/include/lager.hrl b/include/lager.hrl index 8b9bcc7..bf823f9 100644 --- a/include/lager.hrl +++ b/include/lager.hrl @@ -20,15 +20,15 @@ -define(LEVELS, [debug, info, notice, warning, error, critical, alert, emergency, none]). --define(DEBUG, 7). --define(INFO, 6). --define(NOTICE, 5). --define(WARNING, 4). --define(ERROR, 3). --define(CRITICAL, 2). --define(ALERT, 1). --define(EMERGENCY, 0). --define(LOG_NONE, -1). +-define(DEBUG, 128). +-define(INFO, 64). +-define(NOTICE, 32). +-define(WARNING, 16). +-define(ERROR, 8). +-define(CRITICAL, 4). +-define(ALERT, 2). +-define(EMERGENCY, 1). +-define(LOG_NONE, 0). -define(LEVEL2NUM(Level), case Level of @@ -55,7 +55,7 @@ end). -define(SHOULD_LOG(Level), - lager_util:level_to_num(Level) =< element(1, lager_mochiglobal:get(loglevel, {?LOG_NONE, []}))). + (lager_util:level_to_num(Level) band element(1, lager_mochiglobal:get(loglevel, {?LOG_NONE, []}))) /= 0). -define(NOTIFY(Level, Pid, Format, Args), gen_event:notify(lager_event, {log, lager_msg:new(io_lib:format(Format, Args), diff --git a/src/lager.erl b/src/lager.erl index 2264e70..5f3bb9d 100644 --- a/src/lager.erl +++ b/src/lager.erl @@ -24,7 +24,7 @@ %% API -export([start/0, log/3, log/4, - trace_file/2, trace_file/3, trace_console/1, trace_console/2, + trace/2, trace/3, trace_file/2, trace_file/3, trace_console/1, trace_console/2, clear_all_traces/0, stop_trace/1, status/0, get_loglevel/1, set_loglevel/2, set_loglevel/3, get_loglevels/0, minimum_loglevel/1, posix_error/1, @@ -62,21 +62,24 @@ dispatch_log(Severity, Metadata, Format, Args, Size) when is_atom(Severity)-> Pid -> {LevelThreshold,TraceFilters} = lager_mochiglobal:get(loglevel,{?LOG_NONE,[]}), SeverityAsInt=lager_util:level_to_num(Severity), - Destinations = case TraceFilters of - [] -> []; - _ -> - lager_util:check_traces(Metadata,SeverityAsInt,TraceFilters,[]) - end, - case (LevelThreshold >= SeverityAsInt orelse Destinations =/= []) of - true -> + case (LevelThreshold band SeverityAsInt) /= 0 of + true -> + Destinations = case TraceFilters of + [] -> + []; + _ -> + lager_util:check_traces(Metadata,SeverityAsInt,TraceFilters,[]) + end, Timestamp = lager_util:format_time(), - Msg=case Args of - A when is_list(A) ->safe_format_chop(Format,Args,Size); - _ -> Format + Msg = case Args of + A when is_list(A) -> + safe_format_chop(Format,Args,Size); + _ -> + Format end, gen_event:sync_notify(Pid, {log, lager_msg:new(Msg, Timestamp, Severity, Metadata, Destinations)}); - _ -> + _ -> ok end end. @@ -118,7 +121,8 @@ trace_file(File, Filter, Level) -> {MinLevel, Traces} = lager_mochiglobal:get(loglevel), case lists:member(Trace, Traces) of false -> - lager_mochiglobal:put(loglevel, {MinLevel, [Trace|Traces]}); + {_, {mask, TraceMask}, _} = Trace, + lager_mochiglobal:put(loglevel, {MinLevel bor TraceMask, [Trace|Traces]}); _ -> ok end, @@ -134,13 +138,20 @@ trace_console(Filter) -> trace_console(Filter, debug). trace_console(Filter, Level) -> - Trace0 = {Filter, Level, lager_console_backend}, + trace(lager_console_backend, Filter, Level). + +trace(Backend, Filter) -> + trace(Backend, Filter, debug). + +trace(Backend, Filter, Level) -> + Trace0 = {Filter, Level, Backend}, case lager_util:validate_trace(Trace0) of {ok, Trace} -> {MinLevel, Traces} = lager_mochiglobal:get(loglevel), case lists:member(Trace, Traces) of false -> - lager_mochiglobal:put(loglevel, {MinLevel, [Trace|Traces]}); + {_, {mask, TraceMask}, _} = Trace, + lager_mochiglobal:put(loglevel, {MinLevel bor TraceMask, [Trace|Traces]}); _ -> ok end, {ok, Trace}; @@ -149,8 +160,9 @@ trace_console(Filter, Level) -> end. stop_trace({_Filter, _Level, Target} = Trace) -> - {MinLevel, Traces} = lager_mochiglobal:get(loglevel), + {_, Traces} = lager_mochiglobal:get(loglevel), NewTraces = lists:delete(Trace, Traces), + MinLevel = minimum_loglevel(get_loglevels() ++ get_trace_levels(NewTraces)), lager_mochiglobal:put(loglevel, {MinLevel, NewTraces}), case get_loglevel(Target) of none -> @@ -167,7 +179,7 @@ stop_trace({_Filter, _Level, Target} = Trace) -> ok. clear_all_traces() -> - {MinLevel, _Traces} = lager_mochiglobal:get(loglevel), + MinLevel = minimum_loglevel(get_loglevels()), lager_mochiglobal:put(loglevel, {MinLevel, []}), lists:foreach(fun(Handler) -> case get_loglevel(Handler) of @@ -203,8 +215,8 @@ status() -> set_loglevel(Handler, Level) when is_atom(Level) -> Reply = gen_event:call(lager_event, Handler, {set_loglevel, Level}, infinity), %% recalculate min log level - MinLog = minimum_loglevel(get_loglevels()), {_, Traces} = lager_mochiglobal:get(loglevel), + MinLog = minimum_loglevel(get_loglevels() ++ get_trace_levels(Traces)), lager_mochiglobal:put(loglevel, {MinLog, Traces}), Reply. @@ -214,8 +226,8 @@ set_loglevel(Handler, Ident, Level) when is_atom(Level) -> io:format("handler: ~p~n", [{Handler, Ident}]), Reply = gen_event:call(lager_event, {Handler, Ident}, {set_loglevel, Level}, infinity), %% recalculate min log level - MinLog = minimum_loglevel(get_loglevels()), {_, Traces} = lager_mochiglobal:get(loglevel), + MinLog = minimum_loglevel(get_loglevels() ++ get_trace_levels(Traces)), lager_mochiglobal:put(loglevel, {MinLog, Traces}), Reply. @@ -223,6 +235,8 @@ set_loglevel(Handler, Ident, Level) when is_atom(Level) -> %% has multiple identifiers, the lowest is returned get_loglevel(Handler) -> case gen_event:call(lager_event, Handler, get_loglevel, infinity) of + {mask, Mask} -> + erlang:hd(lager_util:mask_to_levels(Mask)); X when is_integer(X) -> lager_util:num_to_level(X); Y -> Y @@ -244,10 +258,17 @@ get_loglevels() -> Handler <- gen_event:which_handlers(lager_event)]. %% @private -minimum_loglevel([]) -> - -1; %% lower than any log level, logging off minimum_loglevel(Levels) -> - erlang:hd(lists:reverse(lists:sort(Levels))). + lists:foldl(fun({mask, Mask}, Acc) -> + Mask bor Acc; + (Level, Acc) when is_integer(Level) -> + lager_util:config_to_mask(lager_util:num_to_level(Level)) bor Acc; + (_, Acc) -> + Acc + end, 0, Levels). + +get_trace_levels(Traces) -> + lists:map(fun({_, Level, _}) -> Level end, Traces). %% @doc Print the format string `Fmt' with `Args' safely with a size %% limit of `Limit'. If the format string is invalid, or not enough diff --git a/src/lager_app.erl b/src/lager_app.erl index 932a213..96060ef 100644 --- a/src/lager_app.erl +++ b/src/lager_app.erl @@ -34,7 +34,7 @@ start() -> start(_StartType, _StartArgs) -> %% until lager is completely started, allow all messages to go through - lager_mochiglobal:put(loglevel, {?DEBUG, []}), + lager_mochiglobal:put(loglevel, {element(2, lager_util:config_to_mask(debug)), []}), {ok, Pid} = lager_sup:start_link(), Handlers = case application:get_env(lager, handlers) of undefined -> diff --git a/src/lager_console_backend.erl b/src/lager_console_backend.erl index 9591fcb..cb9cf95 100644 --- a/src/lager_console_backend.erl +++ b/src/lager_console_backend.erl @@ -43,7 +43,7 @@ init([Level, true]) -> % for backwards compatibility init([Level,false]) -> % for backwards compatibility init([Level,{lager_default_formatter,?TERSE_FORMAT}]); init([Level,{Formatter,FormatterConfig}]) when is_atom(Level), is_atom(Formatter)-> - try lager_util:config_to_level(Level) of + try lager_util:config_to_mask(Level) of Levels -> {ok, #state{level=Levels, formatter=Formatter, @@ -55,10 +55,10 @@ init([Level,{Formatter,FormatterConfig}]) when is_atom(Level), is_atom(Formatte %% @private -handle_call(get_loglevel, #state{level=[Level|_]} = State) -> - {ok, lager_util:level_to_num(Level), State}; +handle_call(get_loglevel, #state{level=Level} = State) -> + {ok, Level, State}; handle_call({set_loglevel, Level}, State) -> - try lager_util:config_to_level(Level) of + try lager_util:config_to_mask(Level) of Levels -> {ok, ok, State#state{level=Levels}} catch @@ -137,7 +137,7 @@ console_log_test_() -> unregister(user), register(user, Pid), erlang:group_leader(Pid, whereis(lager_event)), - lager_mochiglobal:put(loglevel, {?INFO, []}), + lager_mochiglobal:put(loglevel, {element(2, lager_util:config_to_mask(info)), []}), lager:log(info, self(), "Test message"), receive {io_request, From, ReplyAs, {put_chars, unicode, Msg}} -> @@ -156,7 +156,7 @@ console_log_test_() -> register(user, Pid), erlang:group_leader(Pid, whereis(lager_event)), gen_event:add_handler(lager_event, lager_console_backend, [info, true]), - lager_mochiglobal:put(loglevel, {?INFO, []}), + lager_mochiglobal:put(loglevel, {element(2, lager_util:config_to_mask(info)), []}), lager:info("Test message"), lager:info("Test message"), PidStr = pid_to_list(self()), @@ -176,7 +176,7 @@ console_log_test_() -> register(user, Pid), gen_event:add_handler(lager_event, lager_console_backend, info), erlang:group_leader(Pid, whereis(lager_event)), - lager_mochiglobal:put(loglevel, {?INFO, []}), + lager_mochiglobal:put(loglevel, {element(2, lager_util:config_to_mask(info)), []}), lager:debug("Test message"), receive {io_request, From, ReplyAs, {put_chars, unicode, _Msg}} -> @@ -204,7 +204,7 @@ console_log_test_() -> unregister(user), register(user, Pid), gen_event:add_handler(lager_event, lager_console_backend, info), - lager_mochiglobal:put(loglevel, {?INFO, []}), + lager_mochiglobal:put(loglevel, {element(2, lager_util:config_to_mask(info)), []}), erlang:group_leader(Pid, whereis(lager_event)), lager:debug("Test message"), receive @@ -242,7 +242,7 @@ console_log_test_() -> unregister(user), register(user, Pid), gen_event:add_handler(lager_event, lager_console_backend, info), - lager_mochiglobal:put(loglevel, {?INFO, []}), + lager_mochiglobal:put(loglevel, {element(2, lager_util:config_to_mask(info)), []}), lager:set_loglevel(lager_console_backend, '!=info'), erlang:group_leader(Pid, whereis(lager_event)), lager:debug("Test message"), @@ -272,7 +272,7 @@ console_log_test_() -> unregister(user), register(user, Pid), gen_event:add_handler(lager_event, lager_console_backend, info), - lager_mochiglobal:put(loglevel, {?INFO, []}), + lager_mochiglobal:put(loglevel, {element(2, lager_util:config_to_mask(info)), []}), lager:set_loglevel(lager_console_backend, '=debug'), erlang:group_leader(Pid, whereis(lager_event)), lager:debug("Test message"), diff --git a/src/lager_file_backend.erl b/src/lager_file_backend.erl index 227f048..69e7820 100644 --- a/src/lager_file_backend.erl +++ b/src/lager_file_backend.erl @@ -90,8 +90,8 @@ 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) -> - {ok, lager_util:level_to_num(Level), State}; +handle_call(get_loglevel, #state{level=Level} = State) -> + {ok, Level, State}; handle_call(_Request, State) -> {ok, ok, State}. @@ -207,7 +207,7 @@ validate_logfile(H) -> false. validate_loglevel(Level) -> - try lager_util:config_to_level(Level) of + try lager_util:config_to_mask(Level) of Levels -> Levels catch @@ -226,11 +226,11 @@ schedule_rotation(Name, Date) -> get_loglevel_test() -> {ok, Level, _} = handle_call(get_loglevel, - #state{name="bar", level=lager_util:config_to_level(info), fd=0, inode=0}), - ?assertEqual(Level, lager_util:level_to_num(info)), + #state{name="bar", level=lager_util:config_to_mask(info), fd=0, inode=0}), + ?assertEqual(Level, lager_util:config_to_mask(info)), {ok, Level2, _} = handle_call(get_loglevel, - #state{name="foo", level=lager_util:config_to_level(warning), fd=0, inode=0}), - ?assertEqual(Level2, lager_util:level_to_num(warning)). + #state{name="foo", level=lager_util:config_to_mask(warning), fd=0, inode=0}), + ?assertEqual(Level2, lager_util:config_to_mask(warning)). rotation_test() -> {ok, {FD, Inode, _}} = lager_util:open_logfile("test.log", true), diff --git a/src/lager_util.erl b/src/lager_util.erl index c800ccc..b07ec5f 100644 --- a/src/lager_util.erl +++ b/src/lager_util.erl @@ -18,8 +18,8 @@ -include_lib("kernel/include/file.hrl"). --export([levels/0, level_to_num/1, num_to_level/1, config_to_level/1, open_logfile/2, - ensure_logfile/4, rotate_logfile/2, format_time/0, format_time/1, +-export([levels/0, level_to_num/1, num_to_level/1, config_to_mask/1, config_to_levels/1, mask_to_levels/1, + open_logfile/2, ensure_logfile/4, rotate_logfile/2, format_time/0, format_time/1, localtime_ms/0, maybe_utc/1, parse_rotation_date_spec/1, calculate_next_rotation/1, validate_trace/1, check_traces/4, is_loggable/3]). @@ -32,56 +32,76 @@ levels() -> [debug, info, notice, warning, error, critical, alert, emergency]. -level_to_num(debug) -> 7; -level_to_num(info) -> 6; -level_to_num(notice) -> 5; -level_to_num(warning) -> 4; -level_to_num(error) -> 3; -level_to_num(critical) -> 2; -level_to_num(alert) -> 1; -level_to_num(emergency) -> 0; -level_to_num(none) -> -1. - -num_to_level(7) -> debug; -num_to_level(6) -> info; -num_to_level(5) -> notice; -num_to_level(4) -> warning; -num_to_level(3) -> error; -num_to_level(2) -> critical; -num_to_level(1) -> alert; -num_to_level(0) -> emergency; -num_to_level(-1) -> none. +level_to_num(debug) -> ?DEBUG; +level_to_num(info) -> ?INFO; +level_to_num(notice) -> ?NOTICE; +level_to_num(warning) -> ?WARNING; +level_to_num(error) -> ?ERROR; +level_to_num(critical) -> ?CRITICAL; +level_to_num(alert) -> ?ALERT; +level_to_num(emergency) -> ?EMERGENCY; +level_to_num(none) -> ?LOG_NONE. + +num_to_level(?DEBUG) -> debug; +num_to_level(?INFO) -> info; +num_to_level(?NOTICE) -> notice; +num_to_level(?WARNING) -> warning; +num_to_level(?ERROR) -> error; +num_to_level(?CRITICAL) -> critical; +num_to_level(?ALERT) -> alert; +num_to_level(?EMERGENCY) -> emergency; +num_to_level(?LOG_NONE) -> none. + +config_to_mask(Conf) -> + Levels = config_to_levels(Conf), + {mask, lists:foldl(fun(Level, Acc) -> + level_to_num(Level) bor Acc + end, 0, Levels)}. + +mask_to_levels(Mask) -> + mask_to_levels(Mask, levels(), []). + +mask_to_levels(_Mask, [], Acc) -> + lists:reverse(Acc); +mask_to_levels(Mask, [Level|Levels], Acc) -> + NewAcc = case (level_to_num(Level) band Mask) /= 0 of + true -> + [Level|Acc]; + false -> + Acc + end, + mask_to_levels(Mask, Levels, NewAcc). %% TODO, try writing it all out by hand and EQC check it against this code -%config_to_level(X) when X == '>=debug'; X == 'debug' -> +%config_to_levels(X) when X == '>=debug'; X == 'debug' -> %[debug, info, notice, warning, error, critical, alert, emergency]; -%config_to_level(X) when X == '>=info'; X == 'info'; X == '!=debug' -> +%config_to_levels(X) when X == '>=info'; X == 'info'; X == '!=debug' -> %[info, notice, warning, error, critical, alert, emergency]; -config_to_level(Conf) when is_atom(Conf) -> - config_to_level(atom_to_list(Conf)); -config_to_level([$! | Rest]) -> - levels() -- config_to_level(Rest); -config_to_level([$=, $< | Rest]) -> - [_|Levels] = config_to_level(Rest), +config_to_levels(Conf) when is_atom(Conf) -> + config_to_levels(atom_to_list(Conf)); +config_to_levels([$! | Rest]) -> + levels() -- config_to_levels(Rest); +config_to_levels([$=, $< | Rest]) -> + [_|Levels] = config_to_levels(Rest), lists:filter(fun(E) -> not lists:member(E, Levels) end, levels()); -config_to_level([$<, $= | Rest]) -> - [_|Levels] = config_to_level(Rest), +config_to_levels([$<, $= | Rest]) -> + [_|Levels] = config_to_levels(Rest), lists:filter(fun(E) -> not lists:member(E, Levels) end, levels()); -config_to_level([$>, $= | Rest]) -> - Levels = config_to_level(Rest), +config_to_levels([$>, $= | Rest]) -> + Levels = config_to_levels(Rest), lists:filter(fun(E) -> lists:member(E, Levels) end, levels()); -config_to_level([$=, $> | Rest]) -> - Levels = config_to_level(Rest), +config_to_levels([$=, $> | Rest]) -> + Levels = config_to_levels(Rest), lists:filter(fun(E) -> lists:member(E, Levels) end, levels()); -config_to_level([$= | Rest]) -> +config_to_levels([$= | Rest]) -> [level_to_atom(Rest)]; -config_to_level([$< | Rest]) -> - Levels = config_to_level(Rest), +config_to_levels([$< | Rest]) -> + Levels = config_to_levels(Rest), lists:filter(fun(E) -> not lists:member(E, Levels) end, levels()); -config_to_level([$> | Rest]) -> - [_|Levels] = config_to_level(Rest), +config_to_levels([$> | Rest]) -> + [_|Levels] = config_to_levels(Rest), lists:filter(fun(E) -> lists:member(E, Levels) end, levels()); -config_to_level(Conf) -> +config_to_levels(Conf) -> Level = level_to_atom(Conf), lists:dropwhile(fun(E) -> E /= Level end, levels()). @@ -331,7 +351,7 @@ validate_trace({Filter, Level, {Destination, ID}}) when is_list(Filter), is_atom Error end; validate_trace({Filter, Level, Destination}) when is_list(Filter), is_atom(Level), is_atom(Destination) -> - try level_to_num(Level) of + try config_to_mask(Level) of L -> case lists:all(fun({Key, _Value}) when is_atom(Key) -> true; (_) -> false end, Filter) of @@ -350,7 +370,7 @@ validate_trace(_) -> check_traces(_, _, [], Acc) -> lists:flatten(Acc); -check_traces(Attrs, Level, [{_, FilterLevel, _}|Flows], Acc) when Level > FilterLevel -> +check_traces(Attrs, Level, [{_, {mask, FilterLevel}, _}|Flows], Acc) when (Level band FilterLevel) == 0 -> check_traces(Attrs, Level, Flows, Acc); check_traces(Attrs, Level, [{Filter, _, _}|Flows], Acc) when length(Attrs) < length(Filter) -> check_traces(Attrs, Level, Flows, Acc); @@ -378,9 +398,11 @@ check_trace_iter(Attrs, [{Key, Match}|T]) -> end. -spec is_loggable(lager_msg:lager_msg(),integer()|list(),term()) -> boolean(). -is_loggable(Msg, SeverityList, MyName) when is_list(SeverityList) -> +is_loggable(Msg, {mask, Mask}, MyName) -> %% using syslog style comparison flags - lists:member(lager_msg:severity(Msg), SeverityList) orelse + %S = lager_msg:severity_as_int(Msg), + %?debugFmt("comparing masks ~.2B and ~.2B -> ~p~n", [S, Mask, S band Mask]), + (lager_msg:severity_as_int(Msg) band Mask) /= 0 orelse lists:member(MyName, lager_msg:destinations(Msg)); is_loggable(Msg ,SeverityThreshold,MyName) -> lager_msg:severity_as_int(Msg) =< SeverityThreshold orelse @@ -492,30 +514,46 @@ rotate_file_test() -> end || N <- lists:seq(0, 20)]. check_trace_test() -> - ?assertEqual([foo], check_traces([{module, ?MODULE}], 0, [{[{module, ?MODULE}], - 0, foo}, - {[{module, test}], 0, bar}], [])), - ?assertEqual([], check_traces([{module, ?MODULE}], 0, [{[{module, ?MODULE}, - {foo, bar}], 0, foo}, - {[{module, test}], 0, bar}], [])), - ?assertEqual([bar], check_traces([{module, ?MODULE}], 0, [{[{module, ?MODULE}, - {foo, bar}], 0, foo}, - {[{module, '*'}], 0, bar}], [])), - ?assertEqual([bar], check_traces([{module, ?MODULE}], 0, [{[{module, '*'}, - {foo, bar}], 0, foo}, - {[{module, '*'}], 0, bar}], [])), - ?assertEqual([bar], check_traces([{module, ?MODULE}], 0, [{[{module, '*'}, - {foo, '*'}], 0, foo}, - {[{module, '*'}], 0, bar}], [])), - ?assertEqual([bar, foo], check_traces([{module, ?MODULE}, {foo, bar}], 0, [{[{module, '*'}, - {foo, '*'}], 0, foo}, - {[{module, '*'}], 0, bar}], [])), - ?assertEqual([], check_traces([{module, ?MODULE}, {foo, bar}], 6, [{[{module, '*'}, - {foo, '*'}], 0, foo}, - {[{module, '*'}], 0, bar}], [])), - ?assertEqual([foo], check_traces([{module, ?MODULE}, {foo, bar}], 6, [{[{module, '*'}, - {foo, '*'}], 7, foo}, - {[{module, '*'}], 0, bar}], [])), + %% match by module + ?assertEqual([foo], check_traces([{module, ?MODULE}], ?EMERGENCY, [ + {[{module, ?MODULE}], config_to_mask(emergency), foo}, + {[{module, test}], config_to_mask(emergency), bar}], [])), + %% match by module, but other unsatisfyable attribute + ?assertEqual([], check_traces([{module, ?MODULE}], ?EMERGENCY, [ + {[{module, ?MODULE}, {foo, bar}], config_to_mask(emergency), foo}, + {[{module, test}], config_to_mask(emergency), bar}], [])), + %% match by wildcard module + ?assertEqual([bar], check_traces([{module, ?MODULE}], ?EMERGENCY, [ + {[{module, ?MODULE}, {foo, bar}], config_to_mask(emergency), foo}, + {[{module, '*'}], config_to_mask(emergency), bar}], [])), + %% wildcard module, one trace with unsatisfyable attribute + ?assertEqual([bar], check_traces([{module, ?MODULE}], ?EMERGENCY, [ + {[{module, '*'}, {foo, bar}], config_to_mask(emergency), foo}, + {[{module, '*'}], config_to_mask(emergency), bar}], [])), + %% wildcard but not present custom trace attribute + ?assertEqual([bar], check_traces([{module, ?MODULE}], ?EMERGENCY, [ + {[{module, '*'}, {foo, '*'}], config_to_mask(emergency), foo}, + {[{module, '*'}], config_to_mask(emergency), bar}], [])), + %% wildcarding a custom attribute works when it is present + ?assertEqual([bar, foo], check_traces([{module, ?MODULE}, {foo, bar}], ?EMERGENCY, [ + {[{module, '*'}, {foo, '*'}], config_to_mask(emergency), foo}, + {[{module, '*'}], config_to_mask(emergency), bar}], [])), + %% denied by level + ?assertEqual([], check_traces([{module, ?MODULE}, {foo, bar}], ?INFO, [ + {[{module, '*'}, {foo, '*'}], config_to_mask(emergency), foo}, + {[{module, '*'}], config_to_mask(emergency), bar}], [])), + %% allowed by level + ?assertEqual([foo], check_traces([{module, ?MODULE}, {foo, bar}], ?INFO, [ + {[{module, '*'}, {foo, '*'}], config_to_mask(debug), foo}, + {[{module, '*'}], config_to_mask(emergency), bar}], [])), + ?assertEqual([anythingbutnotice, infoandbelow, infoonly], check_traces([{module, ?MODULE}], ?INFO, [ + {[{module, '*'}], config_to_mask('=debug'), debugonly}, + {[{module, '*'}], config_to_mask('=info'), infoonly}, + {[{module, '*'}], config_to_mask('<=info'), infoandbelow}, + {[{module, '*'}], config_to_mask('!=info'), anythingbutinfo}, + {[{module, '*'}], config_to_mask('!=notice'), anythingbutnotice} + ], [])), + ok. is_loggable_test_() -> diff --git a/test/lager_test_backend.erl b/test/lager_test_backend.erl index c761b4b..fab5789 100644 --- a/test/lager_test_backend.erl +++ b/test/lager_test_backend.erl @@ -32,7 +32,7 @@ -endif. init(Level) -> - {ok, #state{level=lager_util:level_to_num(Level), buffer=[], ignored=[]}}. + {ok, #state{level=lager_util:config_to_mask(Level), buffer=[], ignored=[]}}. handle_call(count, #state{buffer=Buffer} = State) -> {ok, length(Buffer), State}; @@ -50,19 +50,21 @@ handle_call(pop, #state{buffer=Buffer} = State) -> handle_call(get_loglevel, #state{level=Level} = State) -> {ok, Level, State}; handle_call({set_loglevel, Level}, State) -> - {ok, ok, State#state{level=lager_util:level_to_num(Level)}}; + {ok, ok, State#state{level=lager_util:config_to_mask(Level)}}; handle_call(_Request, State) -> {ok, ok, State}. handle_event({log, Msg}, - #state{level=LogLevel,buffer=Buffer,ignored=Ignored} = State) -> - case lager_util:is_loggable(Msg, LogLevel, ?MODULE) of - true -> {ok, State#state{buffer=Buffer ++ - [{lager_msg:severity_as_int(Msg), - lager_msg:timestamp(Msg), - lager_msg:message(Msg), lager_msg:metadata(Msg)}]}}; - _ -> {ok, State#state{ignored=Ignored ++ [ignored]}} - end; + #state{level=LogLevel,buffer=Buffer,ignored=Ignored} = State) -> + case lager_util:is_loggable(Msg, LogLevel, ?MODULE) of + true -> + {ok, State#state{buffer=Buffer ++ + [{lager_msg:severity_as_int(Msg), + lager_msg:timestamp(Msg), + lager_msg:message(Msg), lager_msg:metadata(Msg)}]}}; + _ -> + {ok, State#state{ignored=Ignored ++ [ignored]}} + end; handle_event(_Event, State) -> {ok, State}. @@ -170,7 +172,7 @@ lager_test_() -> lager:debug("this message will be ignored"), ?assertEqual(0, count()), ?assertEqual(0, count_ignored()), - lager_mochiglobal:put(loglevel, {?DEBUG, []}), + lager_mochiglobal:put(loglevel, {element(2, lager_util:config_to_mask(debug)), []}), lager:debug("this message should be ignored"), ?assertEqual(0, count()), ?assertEqual(1, count_ignored()), @@ -184,11 +186,11 @@ lager_test_() -> }, {"tracing works", fun() -> - lager_mochiglobal:put(loglevel, {?ERROR, []}), + lager:set_loglevel(?MODULE, error), + lager_mochiglobal:put(loglevel, {element(2, lager_util:config_to_mask(error)), []}), ok = lager:info("hello world"), ?assertEqual(0, count()), - lager_mochiglobal:put(loglevel, {?ERROR, [{[{module, - ?MODULE}], ?DEBUG, ?MODULE}]}), + lager:trace(?MODULE, [{module, ?MODULE}], debug), ok = lager:info("hello world"), ?assertEqual(1, count()), ok @@ -196,15 +198,17 @@ lager_test_() -> }, {"tracing works with custom attributes", fun() -> - lager_mochiglobal:put(loglevel, {?ERROR, []}), + lager:set_loglevel(?MODULE, error), + lager_mochiglobal:put(loglevel, {element(2, lager_util:config_to_mask(error)), []}), lager:info([{requestid, 6}], "hello world"), ?assertEqual(0, count()), - lager_mochiglobal:put(loglevel, {?ERROR, - [{[{requestid, 6}], ?DEBUG, ?MODULE}]}), + lager:trace(?MODULE, [{requestid, 6}, {foo, bar}], debug), lager:info([{requestid, 6}, {foo, bar}], "hello world"), ?assertEqual(1, count()), - lager_mochiglobal:put(loglevel, {?ERROR, - [{[{requestid, '*'}], ?DEBUG, ?MODULE}]}), + lager:trace(?MODULE, [{requestid, '*'}], debug), + lager:info([{requestid, 6}], "hello world"), + ?assertEqual(2, count()), + lager:clear_all_traces(), lager:info([{requestid, 6}], "hello world"), ?assertEqual(2, count()), ok @@ -212,12 +216,15 @@ lager_test_() -> }, {"tracing honors loglevel", fun() -> - lager_mochiglobal:put(loglevel, {?ERROR, [{[{module, - ?MODULE}], ?NOTICE, ?MODULE}]}), + lager:set_loglevel(?MODULE, error), + {ok, T} = lager:trace(?MODULE, [{module, ?MODULE}], notice), ok = lager:info("hello world"), ?assertEqual(0, count()), ok = lager:notice("hello world"), ?assertEqual(1, count()), + lager:stop_trace(T), + ok = lager:notice("hello world"), + ?assertEqual(1, count()), ok end } @@ -714,7 +721,7 @@ error_logger_redirect_test_() -> ?assertEqual(1, count()), ?assertEqual(0, count_ignored()), lager:set_loglevel(?MODULE, error), - lager_mochiglobal:put(loglevel, {?DEBUG, []}), + lager_mochiglobal:put(loglevel, {element(2, lager_util:config_to_mask(debug)), []}), sync_error_logger:info_report([hello, world]), _ = gen_event:which_handlers(error_logger), ?assertEqual(1, count()),