Commit f4f3dd38 authored by Andrew Thompson's avatar Andrew Thompson
Browse files

Rewrite to use a bitmask to represent active loglevels

Also, adapt the rest of lager to use this bitmask as well.
Showing with 207 additions and 141 deletions
+207 -141
......@@ -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),
......
......@@ -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
......
......@@ -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 ->
......
......@@ -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"),
......
......@@ -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),
......
......@@ -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_() ->
......
......@@ -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()),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment