Преглед изворни кода

Merge pull request #389 from erlang-lager/trace_filters

Add several new trace filters
pull/398/head
Mark Allen пре 8 година
committed by GitHub
родитељ
комит
716e1f1099
3 измењених фајлова са 86 додато и 30 уклоњено
  1. +26
    -2
      README.md
  2. +39
    -27
      src/lager_util.erl
  3. +21
    -1
      test/lager_test_backend.erl

+ 26
- 2
README.md Прегледај датотеку

@ -538,7 +538,8 @@ second argument if desired.
You can also specify multiple expressions in a filter, or use the `*` atom as
a wildcard to match any message that has that attribute, regardless of its
value.
value. You may also use the special value `!` to mean, only select if this
key is **not** present.
Tracing to an existing logfile is also supported (but see **Multiple
sink support** below):
@ -566,13 +567,17 @@ data-type that serializes well. To trace by pid, use the pid as a string:
lager:trace_console([{pid, "<0.410.0>"}])
```
As of lager 2.0, you can also use a 3 tuple while tracing, where the second
### Filter expressions
As of lager 3.3.1, you can also use a 3 tuple while tracing where the second
element is a comparison operator. The currently supported comparison operators
are:
* `<` - less than
* `=<` - less than or equal
* `=` - equal to
* `!=` - not equal to
* `>` - greater than
* `>=` - greater than or equal
```erlang
lager:trace_console([{request, '>', 117}, {request, '<', 120}])
@ -580,6 +585,25 @@ lager:trace_console([{request, '>', 117}, {request, '<', 120}])
Using `=` is equivalent to the 2-tuple form.
### Filter composition
As of lager 3.3.1 you may also use the special filter composition keys of
`all` or `any`. For example the filter example above could be
expressed as:
```erlang
lager:trace_console([{all, [{request, '>', 117}, {request, '<', 120}]}])
```
`any` has the effect of "OR style" logical evaluation between filters; `all`
means "AND style" logical evaluation between filters. These compositional filters
expect a list of additional filter expressions as their values.
### Null filters
The `null` filter has a special meaning. A filter of `{null, false}` acts as
a black hole; nothing is passed through. A filter of `{null, true}` means
*everything* passes through. No other values for the null filter are valid and
will be rejected.
### Multiple sink support
If using multiple sinks, there are limitations on tracing that you

+ 39
- 27
src/lager_util.erl Прегледај датотеку

@ -408,44 +408,56 @@ validate_trace(_) ->
validate_trace_filter(Filter) when is_tuple(Filter), is_atom(element(1, Filter)) =:= false ->
false;
validate_trace_filter(Filter) ->
case lists:all(fun({Key, '*'}) when is_atom(Key) -> true;
({Key, '!'}) when is_atom(Key) -> true;
({Key, _Value}) when is_atom(Key) -> true;
({Key, '=', _Value}) when is_atom(Key) -> true;
({Key, '<', _Value}) when is_atom(Key) -> true;
({Key, '>', _Value}) when is_atom(Key) -> true;
(_) -> false end, Filter) of
true ->
true;
_ ->
false
end.
validate_trace_filter(Filter) when is_list(Filter) ->
lists:all(fun validate_trace_filter/1, Filter);
validate_trace_filter({Key, '*'}) when is_atom(Key) -> true;
validate_trace_filter({any, L}) when is_list(L) -> lists:all(fun validate_trace_filter/1, L);
validate_trace_filter({all, L}) when is_list(L) -> lists:all(fun validate_trace_filter/1, L);
validate_trace_filter({null, Bool}) when is_boolean(Bool) -> true;
validate_trace_filter({Key, _Value}) when is_atom(Key) -> true;
validate_trace_filter({Key, '=', _Value}) when is_atom(Key) -> true;
validate_trace_filter({Key, '!=', _Value}) when is_atom(Key) -> true;
validate_trace_filter({Key, '<', _Value}) when is_atom(Key) -> true;
validate_trace_filter({Key, '=<', _Value}) when is_atom(Key) -> true;
validate_trace_filter({Key, '>', _Value}) when is_atom(Key) -> true;
validate_trace_filter({Key, '>=', _Value}) when is_atom(Key) -> true;
validate_trace_filter(_) -> false.
trace_all(Query) ->
glc:all(trace_acc(Query)).
glc:all(trace_acc(Query)).
trace_any(Query) ->
glc:any(Query).
glc:any(Query).
trace_acc(Query) ->
trace_acc(Query, []).
trace_acc([], Acc) ->
lists:reverse(Acc);
lists:reverse(Acc);
trace_acc([{any, L}|T], Acc) ->
trace_acc(T, [glc:any(L)|Acc]);
trace_acc([{all, L}|T], Acc) ->
trace_acc(T, [glc:all(L)|Acc]);
trace_acc([{null, Bool}|T], Acc) ->
trace_acc(T, [glc:null(Bool)|Acc]);
trace_acc([{Key, '*'}|T], Acc) ->
trace_acc(T, [glc:wc(Key)|Acc]);
trace_acc(T, [glc:wc(Key)|Acc]);
trace_acc([{Key, '!'}|T], Acc) ->
trace_acc(T, [glc:nf(Key)|Acc]);
trace_acc(T, [glc:nf(Key)|Acc]);
trace_acc([{Key, Val}|T], Acc) ->
trace_acc(T, [glc:eq(Key, Val)|Acc]);
trace_acc(T, [glc:eq(Key, Val)|Acc]);
trace_acc([{Key, '=', Val}|T], Acc) ->
trace_acc(T, [glc:eq(Key, Val)|Acc]);
trace_acc(T, [glc:eq(Key, Val)|Acc]);
trace_acc([{Key, '!=', Val}|T], Acc) ->
trace_acc(T, [glc:neq(Key, Val)|Acc]);
trace_acc([{Key, '>', Val}|T], Acc) ->
trace_acc(T, [glc:gt(Key, Val)|Acc]);
trace_acc(T, [glc:gt(Key, Val)|Acc]);
trace_acc([{Key, '>=', Val}|T], Acc) ->
trace_acc(T, [glc:gte(Key, Val)|Acc]);
trace_acc([{Key, '=<', Val}|T], Acc) ->
trace_acc(T, [glc:lte(Key, Val)|Acc]);
trace_acc([{Key, '<', Val}|T], Acc) ->
trace_acc(T, [glc:lt(Key, Val)|Acc]).
trace_acc(T, [glc:lt(Key, Val)|Acc]).
check_traces(_, _, [], Acc) ->
lists:flatten(Acc);
@ -464,10 +476,10 @@ check_trace(Attrs, {Filter, _Level, Dest}) when is_tuple(Filter) ->
glc:handle(?DEFAULT_TRACER, Made),
Match = glc_lib:matches(Filter, Made),
case Match of
true ->
Dest;
false ->
[]
true ->
Dest;
false ->
[]
end.
-spec is_loggable(lager_msg:lager_msg(), non_neg_integer()|{'mask', non_neg_integer()}, term()) -> boolean().

+ 21
- 1
test/lager_test_backend.erl Прегледај датотеку

@ -210,7 +210,7 @@ lager_test_() ->
},
{"unsafe logging with args works",
fun() ->
lager:warning("test message ~p", [self()]),
lager:warning_unsafe("test message ~p", [self()]),
?assertEqual(1, count()),
{Level, _Time, Message,_Metadata} = pop(),
?assertMatch(Level, lager_util:level_to_num(warning)),
@ -479,6 +479,26 @@ lager_test_() ->
lager:clear_all_traces(),
lager:info([{requestid, 6}], "hello world"),
?assertEqual(10, count()),
lager:clear_all_traces(),
lager:trace(?MODULE, [{requestid, '>=', 5}, {requestid, '=<', 7}], debug),
lager:info([{requestid, 4}], "nope!"),
lager:info([{requestid, 5}], "hello world"),
lager:info([{requestid, 7}], "hello world again"),
?assertEqual(12, count()),
lager:clear_all_traces(),
lager:trace(?MODULE, [{foo, '!=', bar}]),
lager:info([{foo, bar}], "hello world"),
?assertEqual(12, count()),
lager:info([{foo, baz}], "blarg"),
?assertEqual(13, count()),
lager:clear_all_traces(),
lager:trace(?MODULE, [{all, [{foo, '=', bar}, {null, false}]}]),
lager:info([{foo, bar}], "should not be logged"),
?assertEqual(13, count()),
lager:clear_all_traces(),
lager:trace(?MODULE, [{any, [{foo, '=', bar}, {null, true}]}]),
lager:info([{foo, qux}], "should be logged"),
?assertEqual(14, count()),
ok
end
},

Loading…
Откажи
Сачувај