浏览代码

Only evaluate functions on message emit.

* A side effect is you can set per processes functions via lager:md/1
pull/392/head
walrusVision 8 年前
父节点
当前提交
777fd65df9
共有 4 个文件被更改,包括 55 次插入33 次删除
  1. +3
    -4
      README.md
  2. +11
    -0
      src/lager_default_formatter.erl
  3. +3
    -1
      src/lager_transform.erl
  4. +38
    -28
      test/lager_test_function_transform.erl

+ 3
- 4
README.md 查看文件

@ -649,16 +649,15 @@ add it to `erl_opts`:
```
The MF called should take no arguments and should return a value that can be be
formatted into a log message.
formatted into a log message. Any function which is not defined, loaded, or
throws an exception will return `undefined` or the provided default value.
This metadata is also persistent across processes.
This metadata is also persistent across processes.
**IMPORTANT**: Since you can calling functions, be aware that using these
could have an impact on your logging performance depending on what the call
will need to do.
Also there is no protection against against an undefined module:function or
ensuring any required apps are started.
Setting the truncation limit at compile-time
--------------------------------------------

+ 11
- 0
src/lager_default_formatter.erl 查看文件

@ -185,6 +185,15 @@ make_printable(A,{Align,W}) when is_integer(W) ->
make_printable(A,_W) -> make_printable(A).
run_function(Function, Default) ->
try Function() of
Result ->
Result
catch
_:_ ->
Default
end.
get_metadata(Key, Metadata) ->
get_metadata(Key, Metadata, undefined).
@ -192,6 +201,8 @@ get_metadata(Key, Metadata, Default) ->
case lists:keyfind(Key, 1, Metadata) of
false ->
Default;
{Key, Value} when is_function(Value) ->
run_function(Value, Default);
{Key, Value} ->
Value
end.

+ 3
- 1
src/lager_transform.erl 查看文件

@ -123,7 +123,9 @@ add_function_transforms(_Line, DefaultAttrs, []) ->
add_function_transforms(Line, DefaultAttrs, [{Atom, {Module, Function}}|Remainder]) ->
NewFunction = {tuple, Line, [
{atom, Line, Atom},
{call, Line, {remote, Line, {atom, Line, Module}, {atom, Line, Function}} , []}
{'fun', Line, {
function, {atom, Line, Module}, {atom, Line, Function}, {integer, Line, 0}
}}
]},
add_function_transforms(Line, {cons, Line, NewFunction, DefaultAttrs}, Remainder).

+ 38
- 28
test/lager_test_function_transform.erl 查看文件

@ -24,7 +24,8 @@
-lager_function_transforms([
{returns_static, {lager_test_function_transform, transform_static}},
{returns_dynamic, {lager_test_function_transform, transform_dynamic}}
{returns_dynamic, {lager_test_function_transform, transform_dynamic}},
{returns_undefined, {not_real_module_fake, fake_not_real_function}}
]).
-compile({parse_transform, lager_transform}).
@ -43,7 +44,7 @@ transform_static() ->
static_result.
transform_dynamic() ->
rand:uniform(10).
erlang:monotonic_time().
not_running_test() ->
?assertEqual({error, lager_not_running}, lager:log(info, self(), "not running")).
@ -102,37 +103,46 @@ transform_function_test_() ->
lager:warning("static message"),
?assertEqual(1, lager_test_backend:count()),
{_Level, _Time, _Message, Metadata} = lager_test_backend:pop(),
?assertEqual(transform_static(), proplists:get_value(returns_static, Metadata)),
Function = proplists:get_value(returns_static, Metadata),
?assertEqual(transform_static(), Function()),
ok
end
},
{"Test calling a function which returns content which can change",
fun() ->
lager:warning("dynamic message 1"),
lager:warning("dynamic message 2"),
lager:warning("dynamic message 3"),
lager:warning("dynamic message 4"),
lager:warning("dynamic message 5"),
lager:warning("dynamic message 6"),
?assertEqual(6, lager_test_backend:count()),
{_Level1, _Time1, _Message1, Metadata1} = lager_test_backend:pop(),
Replacement1 = proplists:get_value(returns_dynamic, Metadata1),
?assert((1 =< Replacement1) and (Replacement1 =< 10)),
{_Level2, _Time2, _Message2, Metadata2} = lager_test_backend:pop(),
Replacement2 = proplists:get_value(returns_dynamic, Metadata2),
?assert((1 =< Replacement2) and (Replacement2 =< 10)),
{_Level3, _Time3, _Message3, Metadata3} = lager_test_backend:pop(),
Replacement3 = proplists:get_value(returns_dynamic, Metadata3),
?assert((1 =< Replacement3) and (Replacement3 =< 10)),
{_Level4, _Time4, _Message4, Metadata4} = lager_test_backend:pop(),
Replacement4 = proplists:get_value(returns_dynamic, Metadata4),
?assert((1 =< Replacement4) and (Replacement4 =< 10)),
{_Level5, _Time5, _Message5, Metadata5} = lager_test_backend:pop(),
Replacement5 = proplists:get_value(returns_dynamic, Metadata5),
?assert((1 =< Replacement5) and (Replacement5 =< 10)),
{_Level6, _Time6, _Message6, Metadata6} = lager_test_backend:pop(),
Replacement6 = proplists:get_value(returns_dynamic, Metadata6),
?assert((1 =< Replacement6) and (Replacement6 =< 10)),
lager:warning("dynamic message"),
?assertEqual(1, lager_test_backend:count()),
{_Level, _Time, _Message, Metadata} = lager_test_backend:pop(),
Function = proplists:get_value(returns_dynamic, Metadata),
?assert(Function() < Function()),
?assert(Function() < Function()),
?assert(Function() < Function()),
?assert(Function() < Function()),
ok
end
},
{"Testing a undefined function returns undefined",
fun() ->
lager:warning("Undefined error"),
?assertEqual(1, lager_test_backend:count()),
{_Level, _Time, _Message, Metadata} = lager_test_backend:pop(),
Function = proplists:get_value(returns_undefined, Metadata),
[{module, Module}, {name, Name}|_] = erlang:fun_info(Function),
?assertNot(erlang:function_exported(Module, Name, 0)),
ok
end
},
{"Testing a function provided via metadata",
fun()->
Provided = fun()->
provided_metadata
end,
lager:md([{provided, Provided}]),
lager:warning("Provided metadata"),
?assertEqual(1, lager_test_backend:count()),
{_Level, _Time, _Message, Metadata} = lager_test_backend:pop(),
Function = proplists:get_value(provided, Metadata),
?assertEqual(Provided(), Function()),
ok
end
}

正在加载...
取消
保存