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.
parent 67bce42b
No related merge requests found
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