浏览代码

Allow storage of persistant per-process lager metadata

For persistant processes with some immutable metadata (riak vnode and
the vnode ID, for example), implement lager:md/0 and lager:md/1 for
getting/setting such metadata into the process dictionary.

Such metadata is automatically included in any lager message metadata,
so you can just set it in your init() function or whatever and not have
to worry about passing the data around and using it in every lager call.
pull/121/head
Andrew Thompson 12 年前
父节点
当前提交
98143ae182
共有 3 个文件被更改,包括 59 次插入2 次删除
  1. +28
    -0
      src/lager.erl
  2. +4
    -2
      src/lager_transform.erl
  3. +27
    -0
      test/lager_test_backend.erl

+ 28
- 0
src/lager.erl 查看文件

@ -20,9 +20,12 @@
-include("lager.hrl"). -include("lager.hrl").
-define(LAGER_MD_KEY, '__lager_metadata').
%% API %% API
-export([start/0, -export([start/0,
log/3, log/4, log/3, log/4,
md/0, md/1,
trace/2, trace/3, 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, clear_all_traces/0, stop_trace/1, status/0,
get_loglevel/1, set_loglevel/2, set_loglevel/3, get_loglevels/0, get_loglevel/1, set_loglevel/2, set_loglevel/3, get_loglevels/0,
@ -51,6 +54,31 @@ start_ok(App, {error, {not_started, Dep}}) ->
start_ok(App, {error, Reason}) -> start_ok(App, {error, Reason}) ->
erlang:error({app_start_failed, App, Reason}). erlang:error({app_start_failed, App, Reason}).
%% @doc Get lager metadata for current process
-spec md() -> [{atom(), any()}].
md() ->
case erlang:get(?LAGER_MD_KEY) of
undefined -> [];
MD -> MD
end.
%% @doc Set lager metadata for current process.
%% Will badarg if you don't supply a list of {key, value} tuples keyed by atoms.
-spec md([{atom(), any()},...]) -> ok.
md(NewMD) when is_list(NewMD) ->
%% make sure its actually a real proplist
case lists:all(
fun({Key, _Value}) when is_atom(Key) -> true;
(_) -> false
end, NewMD) of
true ->
erlang:put(?LAGER_MD_KEY, NewMD),
ok;
false ->
erlang:error(badarg)
end;
md(_) ->
erlang:error(badarg).
-spec dispatch_log(log_level(), list(), string(), list() | none, pos_integer()) -> ok | {error, lager_not_running}. -spec dispatch_log(log_level(), list(), string(), list() | none, pos_integer()) -> ok | {error, lager_not_running}.
%% this is the same check that the parse transform bakes into the module at compile time %% this is the same check that the parse transform bakes into the module at compile time

+ 4
- 2
src/lager_transform.erl 查看文件

@ -89,7 +89,9 @@ transform_statement({call, Line, {remote, _Line1, {atom, _Line2, lager},
{cons, Line, {tuple, Line, [ {cons, Line, {tuple, Line, [
{atom, Line, node}, {atom, Line, node},
{call, Line, {atom, Line, node}, []}]}, {call, Line, {atom, Line, node}, []}]},
{nil, Line}}}}}},
%% get the metadata with lager:md(), this will always return a list so we can use it as the tail here
{call, Line, {remote, Line, {atom, Line, lager}, {atom, Line, md}}, []}}}}}},
%{nil, Line}}}}}}},
DefaultAttrs = case erlang:get(application) of DefaultAttrs = case erlang:get(application) of
undefined -> undefined ->
DefaultAttrs0; DefaultAttrs0;
@ -151,7 +153,7 @@ transform_statement({call, Line, {remote, _Line1, {atom, _Line2, lager},
[], [],
%% trick the linter into avoiding a 'term constructed by not used' error: %% trick the linter into avoiding a 'term constructed by not used' error:
%% (fun() -> {error, lager_not_running} end)(); %% (fun() -> {error, lager_not_running} end)();
[{call,9, {'fun',9, {clauses, [{clause,9,[],[], [{tuple,9,[{atom,9,error},{atom,9,lager_not_running}]}]}]}}, []}]},
[{call, Line, {'fun', Line, {clauses, [{clause, Line, [],[], [{tuple, Line, [{atom, Line, error},{atom, Line, lager_not_running}]}]}]}}, []}]},
%% If we care about the loglevel, or there's any traces installed, we have do more checking %% If we care about the loglevel, or there's any traces installed, we have do more checking
%% {Level, Traces} when (Level band SeverityAsInt) /= 0 orelse Traces /= [] -> %% {Level, Traces} when (Level band SeverityAsInt) /= 0 orelse Traces /= [] ->
{clause, Line, {clause, Line,

+ 27
- 0
test/lager_test_backend.erl 查看文件

@ -424,6 +424,33 @@ lager_test_() ->
?assertEqual({?DEBUG bor ?INFO bor ?NOTICE bor ?WARNING bor ?ERROR bor ?CRITICAL bor ?ALERT bor ?EMERGENCY, []}, lager_config:get(loglevel)), ?assertEqual({?DEBUG bor ?INFO bor ?NOTICE bor ?WARNING bor ?ERROR bor ?CRITICAL bor ?ALERT bor ?EMERGENCY, []}, lager_config:get(loglevel)),
ok ok
end end
},
{"metadata in the process dictionary works",
fun() ->
lager:md([{platypus, gravid}, {sloth, hirsute}, {duck, erroneous}]),
lager:info("I sing the animal kingdom electric!"),
{_Level, _Time, _Message, Metadata} = pop(),
?assertEqual(gravid, proplists:get_value(platypus, Metadata)),
?assertEqual(hirsute, proplists:get_value(sloth, Metadata)),
?assertEqual(erroneous, proplists:get_value(duck, Metadata)),
?assertEqual(undefined, proplists:get_value(eagle, Metadata)),
lager:md([{platypus, gravid}, {sloth, hirsute}, {eagle, superincumbent}]),
lager:info("I sing the animal kingdom dielectric!"),
{_Level2, _Time2, _Message2, Metadata2} = pop(),
?assertEqual(gravid, proplists:get_value(platypus, Metadata2)),
?assertEqual(hirsute, proplists:get_value(sloth, Metadata2)),
?assertEqual(undefined, proplists:get_value(duck, Metadata2)),
?assertEqual(superincumbent, proplists:get_value(eagle, Metadata2)),
ok
end
},
{"can't store invalid metadata",
fun() ->
?assertEqual(ok, lager:md([{platypus, gravid}, {sloth, hirsute}, {duck, erroneous}])),
?assertError(badarg, lager:md({flamboyant, flamingo})),
?assertError(badarg, lager:md("zookeeper zephyr")),
ok
end
} }
] ]
}. }.

正在加载...
取消
保存