From 8a178613e37403a59aa9b7c68e2fc63d29f42a9c Mon Sep 17 00:00:00 2001 From: Mark Allen Date: Fri, 8 May 2015 15:53:03 -0500 Subject: [PATCH] Fix errors in dispatch_log/6 parse transform Originally I tried to bodge in a handcoded parse transform and it did not go very well. This time, we simplify the case statement in lager.erl and use this simplified version in the parse transform after getting the AST from the Erlang compiler. --- src/lager.erl | 19 +++---- src/lager_transform.erl | 106 +++++++++++++++++++--------------------- 2 files changed, 57 insertions(+), 68 deletions(-) diff --git a/src/lager.erl b/src/lager.erl index d21a7a1..cfbc303 100644 --- a/src/lager.erl +++ b/src/lager.erl @@ -86,22 +86,17 @@ md(_) -> dispatch_log(Severity, Metadata, Format, Args, Size) when is_atom(Severity)-> dispatch_log(?DEFAULT_SINK, Severity, Metadata, Format, Args, Size). --spec dispatch_log(atom(), log_level(), list(), string(), list() | none, pos_integer()) -> ok | {error, lager_not_running} | {error, {sink_not_configured, term()}}. +-spec dispatch_log(atom(), log_level(), list(), string(), list() | none, pos_integer()) -> ok | {error, lager_not_running} | {error, {sink_not_configured, atom()}}. %% this is the same check that the parse transform bakes into the module at compile time +%% see lager_transform (lines 173-216) dispatch_log(Sink, Severity, Metadata, Format, Args, Size) when is_atom(Severity)-> SeverityAsInt=lager_util:level_to_num(Severity), - case {whereis(Sink), lager_config:get({Sink, loglevel}, {?LOG_NONE, []})} of - {undefined, _} -> - case whereis(lager_event) of - undefined -> - {error, lager_not_running}; - _Pid -> - {error, {sink_not_configured, Sink}} - end; - {SinkPid, {Level, Traces}} when (Level band SeverityAsInt) /= 0 orelse Traces /= [] -> + case {whereis(Sink), whereis(?DEFAULT_SINK), lager_config:get({Sink, loglevel}, {?LOG_NONE, []})} of + {undefined, undefined, _} -> {error, lager_not_running}; + {undefined, _LagerEventPid0, _} -> {error, {sink_not_configured, Sink}}; + {SinkPid, _LagerEventPid1, {Level, Traces}} when (Level band SeverityAsInt) /= 0 orelse Traces /= [] -> do_log(Severity, Metadata, Format, Args, Size, SeverityAsInt, Level, Traces, Sink, SinkPid); - _ -> - ok + _ -> ok end. %% @private Should only be called externally from code generated from the parse transform diff --git a/src/lager_transform.erl b/src/lager_transform.erl index f372d15..1546c04 100644 --- a/src/lager_transform.erl +++ b/src/lager_transform.erl @@ -168,62 +168,56 @@ do_transform(Line, SinkName, Severity, Arguments0) -> LevelVar = make_varname("__Level", Line), TracesVar = make_varname("__Traces", Line), PidVar = make_varname("__Pid", Line), - %% Wrap the call to lager_dispatch log in a case that will avoid doing any work if this message is not elegible for logging - %% case {whereis(Sink), lager_config:get(Sink, loglevel, {?LOG_NONE, []})} of - {'case', Line, - {tuple, Line, - [{call, Line, {atom, Line, whereis}, [{atom, Line, SinkName}]}, - {call, Line, {remote, Line, {atom, Line, lager_config}, {atom, Line, get}}, [{tuple, Line, [{atom, Line, SinkName}, {atom, Line, loglevel}]}, {tuple, Line, [{integer, Line, 0},{nil, Line}]}]}]}, - [ - %% {undefined, _} -> - {clause, Line, - [{tuple, Line, [{atom, Line, undefined}, {var, Line, '_'}]}], - [], - {'case', Line, %% case whereis(lager_event) of - {call, Line, {atom, Line, whereis}, [{atom, Line, lager_event}]}, - [{clause, Line, % undefined -> {error, lager_not_running}; - [{atom, Line, undefined}], - [], - %% trick the linter into avoiding a 'term constructed by not used' error: - %% (fun() -> {error, lager_not_running} end)(); - [{call, Line, {'fun', Line, {clauses, [{clause, Line, [],[], [{tuple, Line, [{atom, Line, error},{atom, Line, lager_not_running}]}]}]}}, []}] - }, - {clause, Line, % _ -> - [{var, Line, '_'}], - [], - %% same trick - %% (fun() -> {error, {sink_not_configured, SinkName}} end)(); - [{call, Line, {'fun', Line, {clauses, [{clause, Line, [],[], [{tuple, Line, [{atom, Line, error}, [{tuple, Line, [{atom, Line, lager_not_running}, {atom, Line, SinkName}]}]]}]}]}}}], [] - }] - }}, - %% 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 /= [] -> - {clause, Line, - [{tuple, Line, [{var, Line, PidVar}, {tuple, Line, [{var, Line, LevelVar}, {var, Line, TracesVar}]}]}], - [[{op, Line, 'orelse', - {op, Line, '/=', {op, Line, 'band', {var, Line, LevelVar}, {integer, Line, SeverityAsInt}}, {integer, Line, 0}}, - {op, Line, '/=', {var, Line, TracesVar}, {nil, Line}}}]], - [ - %% do the call to lager:dispatch_log/9 - {call, Line, {remote, Line, {atom, Line, lager}, {atom, Line, do_log}}, - [ - {atom,Line,Severity}, - Traces, - Message, - Arguments, - {integer, Line, get(truncation_size)}, - {integer, Line, SeverityAsInt}, - {var, Line, LevelVar}, - {var, Line, TracesVar}, - {atom, Line, SinkName}, - {var, Line, PidVar} - ] - } - ]}, - %% otherwise, do nothing - %% _ -> ok - {clause, Line, [{var, Line, '_'}],[],[{atom, Line, ok}]} - ]}. + %% Wrap the call to lager:dispatch_log/6 in case that will avoid doing any work if this message is not elegible for logging + %% See lager.erl (lines 89-100) for lager:dispatch_log/6 + %% case {whereis(Sink), whereis(?DEFAULT_SINK), lager_config:get({Sink, loglevel}, {?LOG_NONE, []})} of + {'case',Line, + {tuple,Line, + [{call,Line,{atom,Line,whereis},[{atom,Line,SinkName}]}, + {call,Line,{atom,Line,whereis},[{atom,Line,lager_event}]}, %% <--lager_event is ?DEFAULT_SINK + {call,Line, + {remote,Line,{atom,Line,lager_config},{atom,Line,get}}, + [{tuple,Line,[{atom,Line,SinkName},{atom,Line,loglevel}]}, + {tuple,Line,[{integer,Line,0},{nil,1}]}]}]}, + %% {undefined, undefined, _} -> {error, lager_not_running}; + [{clause,Line, + [{tuple,Line, + [{atom,Line,undefined},{atom,Line,undefined},{var,Line,'_'}]}], + [], + %% trick the linter into avoiding a 'term constructed but not used' error: + %% (fun() -> {error, lager_not_running} end)() + [{call, Line, {'fun', Line, {clauses, [{clause, Line, [],[], [{tuple, Line, [{atom, Line, error},{atom, Line, lager_not_running}]}]}]}}, []}] + }, + %% {undefined, _, _} -> {error, {sink_not_configured, Sink}}; + {clause,Line, + [{tuple,Line, + [{atom,Line,undefined},{var,Line,'_'},{var,Line,'_'}]}], + [], + %% same trick as above to avoid linter error + [{call, Line, {'fun', Line, {clauses, [{clause, Line, [],[], [{tuple,Line, [{atom,Line,error}, {tuple,Line,[{atom,Line,sink_not_configured},{atom,Line,SinkName}]}]}]}]}}, []}] + }, + %% {SinkPid, _, {Level, Traces}} when ... -> lager:do_log/9; + {clause,Line, + [{tuple,Line, + [{var,Line,PidVar}, + {var,Line,'_'}, + {tuple,Line,[{var,Line,LevelVar},{var,Line,TracesVar}]}]}], + [[{op, Line, 'orelse', + {op, Line, '/=', {op, Line, 'band', {var, Line, LevelVar}, {integer, Line, SeverityAsInt}}, {integer, Line, 0}}, + {op, Line, '/=', {var, Line, TracesVar}, {nil, Line}}}]], + [{call,Line,{remote, Line, {atom, Line, lager}, {atom, Line, do_log}}, + [{atom,Line,Severity}, + Traces, + Message, + Arguments, + {integer, Line, get(truncation_size)}, + {integer, Line, SeverityAsInt}, + {var, Line, LevelVar}, + {var, Line, TracesVar}, + {atom, Line, SinkName}, + {var, Line, PidVar}]}]}, + %% _ -> ok + {clause,Line,[{var,Line,'_'}],[],[{atom,Line,ok}]}]}. make_varname(Prefix, Line) -> list_to_atom(Prefix ++ atom_to_list(get(module)) ++ integer_to_list(Line)).