Browse Source

Merge 244463e954 into 91575d4479

pull/524/merge
Andrew Thompson 4 years ago
committed by GitHub
parent
commit
06091f79f6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 401 additions and 104 deletions
  1. +63
    -0
      README.md
  2. +61
    -1
      src/lager.erl
  3. +21
    -6
      src/lager_app.erl
  4. +119
    -0
      src/lager_logger_formatter.erl
  5. +23
    -18
      src/lager_sup.erl
  6. +114
    -79
      src/lager_transform.erl

+ 63
- 0
README.md View File

@ -1153,6 +1153,69 @@ Example Usage:
:lager.warning('Some message with a term: ~p', [term]) :lager.warning('Some message with a term: ~p', [term])
``` ```
Integration with OTP's Logger
-----------------------------
Now that OTP includes a modern log event pipeline, the Lager project has decided
to work on winding down Lager development in favor of unifying the Erlang
ecosystem behind Logger. To that end, Lager now supports being configured to use
its parse transform to rewrite lager calls into logger calls. To enable this
mode, the following changes are required:
In sys.config:
```
[
{kernel,
[{logger,
[{handler, default, logger_std_h,
#{formatter => {lager_logger_formatter, #{report_cb => fun lager_logger_formatter:report_cb/1}}}},
]}]},
...
{lager, [
{lager_use_logger, true},
...
]}
]
```
The logger stanza changes are not needed if you wish to use logger's default
formatter.
In your applications top level rebar.config (probably requires rebar3):
```
{overrides, [{add, [{erl_opts, [{lager_use_logger, true}]}]}]}.
```
This will force the parse transform configuration to apply to all the
dependencies as well. Make sure you've defined the lager version in your
toplevel application's rebar.config and that the version is high enough to
support these options. A toplevel dependency will override any lager
dependencies in any of your application's dependencies and thus ensure the parse
transform is the right version.
To generate a logger configuration from your lager configuration you can do:
```
lager:generate_logger_configuration()
```
If you wish to simply use your existing lager configuration as is, and have
lager configure logger you can, in your sys.config in the lager stanza:
```
{lager, [
{configure_logger, true},
...
]}
```
Alternatively you can use:
```
lager:configure_logger()
```
3.x Changelog 3.x Changelog
------------- -------------

+ 61
- 1
src/lager.erl View File

@ -40,7 +40,8 @@
get_loglevel/1, get_loglevel/2, set_loglevel/2, set_loglevel/3, set_loglevel/4, get_loglevels/1, get_loglevel/1, get_loglevel/2, set_loglevel/2, set_loglevel/3, set_loglevel/4, get_loglevels/1,
update_loglevel_config/1, posix_error/1, set_loghwm/2, set_loghwm/3, set_loghwm/4, update_loglevel_config/1, posix_error/1, set_loghwm/2, set_loghwm/3, set_loghwm/4,
safe_format/3, safe_format_chop/3, unsafe_format/2, dispatch_log/5, dispatch_log/7, dispatch_log/9, safe_format/3, safe_format_chop/3, unsafe_format/2, dispatch_log/5, dispatch_log/7, dispatch_log/9,
do_log/9, do_log/10, do_log_unsafe/10, pr/2, pr/3, pr_stacktrace/1, pr_stacktrace/2]).
do_log/9, do_log/10, do_log_unsafe/10, pr/2, pr/3, pr_stacktrace/1, pr_stacktrace/2,
generate_logger_config/0, configure_logger/0]).
-type log_level() :: none | debug | info | notice | warning | error | critical | alert | emergency. -type log_level() :: none | debug | info | notice | warning | error | critical | alert | emergency.
-type log_level_number() :: 0..7. -type log_level_number() :: 0..7.
@ -695,6 +696,65 @@ rotate_handler(Handler) ->
rotate_handler(Handler, Sink) -> rotate_handler(Handler, Sink) ->
gen_event:call(Sink, Handler, rotate, ?ROTATE_TIMEOUT). gen_event:call(Sink, Handler, rotate, ?ROTATE_TIMEOUT).
generate_logger_config() ->
Handlers = application:get_env(lager, handlers, lager_app:default_handlers()),
{Level, NewHandlers} = generate_logger_handlers(Handlers, {notice, []}),
{kernel, [{logger_level, Level}, {logger, NewHandlers}]}.
configure_logger() ->
Handlers = application:get_env(lager, handlers, lager_app:default_handlers()),
WhitelistedLoggerHandlers = application:get_env(lager, whitelisted_logger_handlers, []),
[ ok = logger:remove_handler(Id) || #{id := Id} <- logger:get_handler_config(), not lists:member(Id, WhitelistedLoggerHandlers) ],
{Level, NewHandlers} = generate_logger_handlers(Handlers, {notice, []}),
logger:set_primary_config(maps:merge(logger:get_primary_config(), #{level => Level})),
[ ok = logger:add_handler(HandlerId, HandlerModule, HandlerConfig) || {handler, HandlerId, HandlerModule, HandlerConfig} <- NewHandlers ],
ok.
generate_logger_handlers([], Acc) ->
Acc;
generate_logger_handlers([{lager_console_backend, Config}|Tail], {CurrentLevel, Acc}) ->
Level = proplists:get_value(level, Config, info),
Formatter = proplists:get_value(formatter, Config, lager_default_formatter),
FormatterConfig = proplists:get_value(formatter_config, Config, []),
Handler = {handler, console, logger_std_h, #{level => Level, formatter =>
{lager_logger_formatter, #{report_cb => fun lager_logger_formatter:report_cb/1,
formatter => Formatter,
formatter_config => FormatterConfig}}}},
NewLevel = case lager_util:level_to_num(Level) > lager_util:level_to_num(CurrentLevel) of
true ->
Level;
false ->
CurrentLevel
end,
generate_logger_handlers(Tail, {NewLevel, [Handler|Acc]});
generate_logger_handlers([{lager_file_backend, Config}|Tail], {CurrentLevel, Acc}) ->
Level = proplists:get_value(level, Config, info),
File = proplists:get_value(file, Config),
LogRoot = application:get_env(lager, log_root, ""),
Size = proplists:get_value(size, Config, 10485760),
Count = proplists:get_value(count, Config, 5),
Formatter = proplists:get_value(formatter, Config, lager_default_formatter),
FormatterConfig = proplists:get_value(formatter_config, Config, []),
%% the standard log handler has a file mode with size based rotation support that is much saner than
%% disk_log's, so use that here
Handler = {handler, list_to_atom(File), logger_std_h, #{level => Level,
config => #{type => file,
file => filename:join(LogRoot, File),
max_no_files => Count,
max_no_bytes => Size},
formatter =>
{lager_logger_formatter, #{report_cb => fun lager_logger_formatter:report_cb/1,
formatter => Formatter,
formatter_config => FormatterConfig}}}},
NewLevel = case lager_util:level_to_num(Level) > lager_util:level_to_num(CurrentLevel) of
true ->
Level;
false ->
CurrentLevel
end,
generate_logger_handlers(Tail, {NewLevel, [Handler|Acc]}).
%% @private %% @private
trace_func(#trace_func_state_v1{pid=Pid, level=Level, format_string=Fmt}=FuncState, Event, ProcState) -> trace_func(#trace_func_state_v1{pid=Pid, level=Level, format_string=Fmt}=FuncState, Event, ProcState) ->
_ = lager:log(Level, Pid, Fmt, [Event, ProcState]), _ = lager:log(Level, Pid, Fmt, [Event, ProcState]),

+ 21
- 6
src/lager_app.erl View File

@ -30,7 +30,8 @@
start_handler/3, start_handler/3,
configure_sink/2, configure_sink/2,
stop/1, stop/1,
boot/1]).
boot/1,
default_handlers/0]).
%% The `application:get_env/3` compatibility wrapper was useful %% The `application:get_env/3` compatibility wrapper was useful
%% for other modules in r15 and before %% for other modules in r15 and before
@ -225,11 +226,22 @@ get_env(Application, Key, Default) ->
start(_StartType, _StartArgs) -> start(_StartType, _StartArgs) ->
{ok, Pid} = lager_sup:start_link(), {ok, Pid} = lager_sup:start_link(),
SavedHandlers = boot(),
_ = boot('__all_extra'),
_ = boot('__traces'),
clean_up_config_checks(),
{ok, Pid, SavedHandlers}.
case application:get_env(lager, lager_use_logger, false) of
false ->
SavedHandlers = boot(),
_ = boot('__all_extra'),
_ = boot('__traces'),
clean_up_config_checks(),
{ok, Pid, SavedHandlers};
true ->
case application:get_env(lager, configure_logger, false) of
true ->
ok = lager:configure_logger();
false ->
ok
end,
{ok, Pid}
end.
boot() -> boot() ->
%% Handle the default sink. %% Handle the default sink.
@ -276,6 +288,9 @@ stop(Handlers) ->
end, Handlers), end, Handlers),
lager_config:cleanup(). lager_config:cleanup().
default_handlers() ->
?DEFAULT_HANDLER_CONF.
expand_handlers([]) -> expand_handlers([]) ->
[]; [];
expand_handlers([{lager_file_backend, [{Key, _Value}|_]=Config}|T]) when is_atom(Key) -> expand_handlers([{lager_file_backend, [{Key, _Value}|_]=Config}|T]) when is_atom(Key) ->

+ 119
- 0
src/lager_logger_formatter.erl View File

@ -0,0 +1,119 @@
-module(lager_logger_formatter).
%% convert logger formatter calls into lager formatter ones
-export([report_cb/1, format/2]).%, check_config/1]).
report_cb(#{label := {gen_server, terminate}, name := Name, reason := Reason}) ->
Formatted = error_logger_lager_h:format_reason(Reason),
{"gen_server ~w terminated with reason: ~s", [Name, Formatted]};
report_cb(#{label := {gen_fsm, terminate}, name := Name, state_name := StateName, reason := Reason}) ->
Formatted = error_logger_lager_h:format_reason(Reason),
{"gen_fsm ~w in state ~w terminated with reason: ~s", [Name, StateName, Formatted]};
report_cb(#{label := {gen_event, terminate}, name := Name, handler := Handler, reason := Reason}) ->
Formatted = error_logger_lager_h:format_reason(Reason),
{"gen_event ~w installed in ~w terminated with reason: ~s", [Handler, Name, Formatted]};
report_cb(#{label := {gen_statem, terminate}, name := Name, reason := Reason}) ->
Formatted = error_logger_lager_h:format_reason(Reason),
%% XXX I can't find the FSM statename in the error report, maybe it should be added
{"gen_statem ~w terminated with reason: ~s", [Name, Formatted]};
report_cb(#{msg := {report, #{label := {Behaviour, no_handle_info}, mod := Mod, msg := Msg}}}) ->
{"undefined handle_info for ~p in ~s ~p", [Msg, Behaviour, Mod]};
report_cb(#{label := {supervisor, progress}, report := Report}) ->
case application:get_env(lager, suppress_supervisor_start_stop, false) of
true ->
{"", []};
false ->
{supervisor, Name} = lists:keyfind(supervisor, 1, Report),
{started, Started} = lists:keyfind(started, 1, Report),
case lists:keyfind(id, 1, Started) of
false ->
%% supervisor itself starting
{mfa, {Module, Function, Args}} = lists:keyfind(mfa, 1, Started),
{pid, Pid} = lists:keyfind(pid, 1, Started),
{"Supervisor ~w started as ~p at pid ~w", [Name, error_logger_lager_h:format_mfa({Module, Function, Args}), Pid]};
{id, ChildID} ->
case lists:keyfind(pid, 1, Started) of
{pid, Pid} ->
{"Supervisor ~w started child ~p at pid ~w", [Name, ChildID, Pid]};
false ->
%% children is a list of pids for some reason? and we only get the count
{nb_children, ChildCount} = lists:keyfind(nb_children, 1, Started),
{"Supervisor ~w started ~b children ~p", [Name, ChildCount, ChildID]}
end
end
end;
report_cb(#{label := {supervisor, _Error}, report := Report}) ->
{supervisor, Name} = lists:keyfind(supervisor, 1, Report),
{reason, Reason} = lists:keyfind(reason, 1, Report),
Formatted = error_logger_lager_h:format_reason(Reason),
{errorContext, ErrorContext} = lists:keyfind(errorContext, 1, Report),
{offender, Offender} = lists:keyfind(offender, 1, Report),
case lists:keyfind(mod, 1, Offender) of
{mod, _Mod} ->
{pid, Pid} = lists:keyfind(pid, 1, Offender),
%% this comes from supervisor_bridge
{"Supervisor ~w had ~p ~p with reason ~s", [Name, Pid, ErrorContext, Formatted]};
false ->
{id, ChildID} = lists:keyfind(id, 1, Offender),
case lists:keyfind(pid, 1, Offender) of
{pid, Pid} ->
{"Supervisor ~w had ~p ~p ~p with reason ~s", [Name, ChildID, Pid, ErrorContext, Formatted]};
false ->
{"Supervisor ~w had ~p ~p with reason ~s", [Name, ChildID, ErrorContext, Formatted]}
end
end;
report_cb(#{label := {application_controller, progress}, report := Report}) ->
case application:get_env(lager, suppress_application_start_stop, false) of
true -> {"", []};
false ->
{application, Name} = lists:keyfind(application, 1, Report),
{started_at, Node} = lists:keyfind(started_at, 1, Report),
{"Application ~w started on node ~w", [Name, Node]}
end;
report_cb(#{label := {application_controller, exit}, report := Report}) ->
{exited, Reason} = lists:keyfind(exited, 1, Report),
case application:get_env(lager, suppress_application_start_stop) of
{ok, true} when Reason == stopped ->
{"", []};
_ ->
{application, Name} = lists:keyfind(application, 1, Report),
Formatted = error_logger_lager_h:format_reason(Reason),
{"Application ~w exited with reason: ~s", [Name, Formatted]}
end.
%% TODO handle proc_lib crash
format(#{msg := {report, _Report}, meta := Metadata} = Event, #{report_cb := Fun} = Config) when is_function(Fun, 1); is_function(Fun, 2) ->
format(Event#{meta => Metadata#{report_cb => Fun}}, maps:remove(report_cb, Config));
format(#{level := _Level, msg := {report, Report}, meta := #{report_cb := Fun}} = Event, Config) when is_function(Fun, 1) ->
case Fun(Report) of
{"", []} -> "";
{Format, Args} when is_list(Format), is_list(Args) ->
format(Event#{msg => {Format, Args}}, Config)
end;
format(#{level := Level, msg := {string, String}, meta := Metadata}, Config) ->
do_format(Level, String, Metadata, Config);
format(#{level := Level, msg := {FmtStr, FmtArgs}, meta := Metadata}, Config) ->
Msg = lager_format:format(FmtStr, FmtArgs, maps:get(max_size, Config, 1024)),
do_format(Level, Msg, Metadata, Config).
do_format(Level, Msg, Metadata, Config) ->
FormatModule = maps:get(formatter, Config, lager_default_formatter),
Timestamp = maps:get(time, Metadata),
MegaSecs = Timestamp div 1000000000000,
Secs = (Timestamp rem 1000000000000) div 1000000,
MicroSecs = (Timestamp rem 1000000000000) rem 1000000,
{Colors, End} = case maps:get(colors, Config, false) of
true ->
{application:get_env(lager, colors, []), "\e[0m"};
false ->
{[], ""}
end,
[FormatModule:format(lager_msg:new(Msg, {MegaSecs, Secs, MicroSecs}, Level, convert_metadata(Metadata), []), maps:get(formatter_config, Config, []), Colors), End].
convert_metadata(Metadata) ->
maps:fold(fun(mfa, {Module, Function, Arity}, Acc) ->
[{module, Module}, {function, Function}, {arity, Arity}|Acc];
(K, V, Acc) ->
[{K, V}|Acc]
end, [], Metadata).

+ 23
- 18
src/lager_sup.erl View File

@ -32,24 +32,29 @@ start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []). supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init([]) -> init([]) ->
%% set up the config, is safe even during relups
lager_config:new(),
%% TODO:
%% Always start lager_event as the default and make sure that
%% other gen_event stuff can start up as needed
%%
%% Maybe a new API to handle the sink and its policy?
Children = [
{lager, {gen_event, start_link, [{local, lager_event}]},
permanent, 5000, worker, dynamic},
{lager_handler_watcher_sup, {lager_handler_watcher_sup, start_link, []},
permanent, 5000, supervisor, [lager_handler_watcher_sup]}],
CrashLog = decide_crash_log(application:get_env(lager, crash_log, false)),
{ok, {{one_for_one, 10, 60},
Children ++ CrashLog
}}.
case application:get_env(lager, lager_use_logger, false) of
true ->
{ok, {{one_for_one, 10, 60}, []}};
false ->
%% set up the config, is safe even during relups
lager_config:new(),
%% TODO:
%% Always start lager_event as the default and make sure that
%% other gen_event stuff can start up as needed
%%
%% Maybe a new API to handle the sink and its policy?
Children = [
{lager, {gen_event, start_link, [{local, lager_event}]},
permanent, 5000, worker, dynamic},
{lager_handler_watcher_sup, {lager_handler_watcher_sup, start_link, []},
permanent, 5000, supervisor, [lager_handler_watcher_sup]}],
CrashLog = decide_crash_log(application:get_env(lager, crash_log, false)),
{ok, {{one_for_one, 10, 60},
Children ++ CrashLog
}}
end.
validate_positive({ok, Val}, _Default) when is_integer(Val) andalso Val >= 0 -> validate_positive({ok, Val}, _Default) when is_integer(Val) andalso Val >= 0 ->
Val; Val;

+ 114
- 79
src/lager_transform.erl View File

@ -33,10 +33,12 @@ parse_transform(AST, Options) ->
Enable = proplists:get_value(lager_print_records_flag, Options, true), Enable = proplists:get_value(lager_print_records_flag, Options, true),
Sinks = [lager] ++ proplists:get_value(lager_extra_sinks, Options, []), Sinks = [lager] ++ proplists:get_value(lager_extra_sinks, Options, []),
Functions = proplists:get_value(lager_function_transforms, Options, []), Functions = proplists:get_value(lager_function_transforms, Options, []),
UseLogger = proplists:get_value(lager_use_logger, Options, false),
put(print_records_flag, Enable), put(print_records_flag, Enable),
put(truncation_size, TruncSize), put(truncation_size, TruncSize),
put(sinks, Sinks), put(sinks, Sinks),
put(functions, lists:keysort(1, Functions)), put(functions, lists:keysort(1, Functions)),
put(use_logger, UseLogger),
erlang:put(records, []), erlang:put(records, []),
%% .app file should either be in the outdir, or the same dir as the source file %% .app file should either be in the outdir, or the same dir as the source file
guess_application(proplists:get_value(outdir, Options), hd(AST)), guess_application(proplists:get_value(outdir, Options), hd(AST)),
@ -63,6 +65,7 @@ walk_ast(Acc, [{attribute, _, lager_function_transforms, FromModule }=H|T]) ->
walk_ast([H|Acc], T); walk_ast([H|Acc], T);
walk_ast(Acc, [{function, Line, Name, Arity, Clauses}|T]) -> walk_ast(Acc, [{function, Line, Name, Arity, Clauses}|T]) ->
put(function, Name), put(function, Name),
put(arity, Arity),
walk_ast([{function, Line, Name, Arity, walk_ast([{function, Line, Name, Arity,
walk_clauses([], Clauses)}|Acc], T); walk_clauses([], Clauses)}|Acc], T);
walk_ast(Acc, [{attribute, _, record, {Name, Fields}}=H|T]) -> walk_ast(Acc, [{attribute, _, record, {Name, Fields}}=H|T]) ->
@ -140,24 +143,40 @@ do_transform(Line, SinkName, Severity, Arguments0) ->
do_transform(Line, SinkName, Severity, Arguments0, safe). do_transform(Line, SinkName, Severity, Arguments0, safe).
do_transform(Line, SinkName, Severity, Arguments0, Safety) -> do_transform(Line, SinkName, Severity, Arguments0, Safety) ->
SeverityAsInt=lager_util:level_to_num(Severity),
DefaultAttrs0 = {cons, Line, {tuple, Line, [
{atom, Line, module}, {atom, Line, get(module)}]},
{cons, Line, {tuple, Line, [
{atom, Line, function}, {atom, Line, get(function)}]},
{cons, Line, {tuple, Line, [
{atom, Line, line},
{integer, Line, Line}]},
{cons, Line, {tuple, Line, [
{atom, Line, pid},
{call, Line, {atom, Line, pid_to_list}, [
{call, Line, {atom, Line ,self}, []}]}]},
{cons, Line, {tuple, Line, [
{atom, Line, node},
{call, Line, {atom, Line, node}, []}]},
%% 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}}}}}}},
DefaultAttrs0 = case get(use_logger) of
true ->
{cons, Line, {tuple, Line, [
{atom, Line, pid}, {call, Line, {atom, Line, self}, []}]},
{cons, Line, {tuple, Line, [
{atom, Line, gl}, {call, Line, {atom, Line, group_leader}, []}]},
{cons, Line, {tuple, Line, [
{atom, Line, time}, {call, Line, {remote, Line, {atom, Line, erlang}, {atom, Line, system_time}}, [{atom, Line, microsecond}]}]},
{cons, Line, {tuple, Line, [
{atom, Line, mfa}, {tuple, Line, [{atom, Line, get(module)}, {atom, Line, get(function)}, {atom, Line, get(arity)}]}]},
{cons, Line, {tuple, Line, [
{atom, Line, file}, {string, Line, get(filename)}]},
{cons, Line, {tuple, Line, [
{atom, Line, line}, {integer, Line, 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}}, []}}}}}}};
false ->
{cons, Line, {tuple, Line, [
{atom, Line, module}, {atom, Line, get(module)}]},
{cons, Line, {tuple, Line, [
{atom, Line, function}, {atom, Line, get(function)}]},
{cons, Line, {tuple, Line, [
{atom, Line, line},
{integer, Line, Line}]},
{cons, Line, {tuple, Line, [
{atom, Line, pid},
{call, Line, {atom, Line, pid_to_list}, [
{call, Line, {atom, Line ,self}, []}]}]},
{cons, Line, {tuple, Line, [
{atom, Line, node},
{call, Line, {atom, Line, node}, []}]},
%% 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}}, []}}}}}}
end,
Functions = get(functions), Functions = get(functions),
DefaultAttrs1 = add_function_transforms(Line, DefaultAttrs0, Functions), DefaultAttrs1 = add_function_transforms(Line, DefaultAttrs0, Functions),
DefaultAttrs = case erlang:get(application) of DefaultAttrs = case erlang:get(application) of
@ -171,67 +190,82 @@ do_transform(Line, SinkName, Severity, Arguments0, Safety) ->
{nil, Line}}, DefaultAttrs1) {nil, Line}}, DefaultAttrs1)
end, end,
{Meta, Message, Arguments} = handle_args(DefaultAttrs, Line, Arguments0), {Meta, Message, Arguments} = handle_args(DefaultAttrs, Line, Arguments0),
%% Generate some unique variable names so we don't accidentally export from case clauses.
%% Note that these are not actual atoms, but the AST treats variable names as atoms.
LevelVar = make_varname("__Level", Line),
TracesVar = make_varname("__Traces", Line),
PidVar = make_varname("__Pid", Line),
LogFun = case Safety of
safe ->
do_log;
unsafe ->
do_log_unsafe
end,
%% 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,?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,Line}]}]}]},
%% {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, LogFun}},
[{atom,Line,Severity},
Meta,
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}]}]}.
case get(use_logger) of
true ->
case Arguments of
{atom, _, none} ->
%% logger:log(Level, Format, Args, Metadata)
{call,Line,{remote, Line, {atom, Line, logger}, {atom, Line, log}},
[{atom,Line,Severity}, Message, {call, Line, {remote, Line, {atom, Line, maps}, {atom, Line, from_list}}, [Meta]}]};
_ ->
%% logger:log(Level, String, Metadata)
{call,Line,{remote, Line, {atom, Line, logger}, {atom, Line, log}},
[{atom,Line,Severity}, Message, Arguments, {call, Line, {remote, Line, {atom, Line, maps}, {atom, Line, from_list}}, [Meta]}]}
end;
false ->
SeverityAsInt=lager_util:level_to_num(Severity),
%% Generate some unique variable names so we don't accidentally export from case clauses.
%% Note that these are not actual atoms, but the AST treats variable names as atoms.
LevelVar = make_varname("__Level", Line),
TracesVar = make_varname("__Traces", Line),
PidVar = make_varname("__Pid", Line),
LogFun = case Safety of
safe ->
do_log;
unsafe ->
do_log_unsafe
end,
%% 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,?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,Line}]}]}]},
%% {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, LogFun}},
[{atom,Line,Severity},
Meta,
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}]}]}
end.
handle_args(DefaultAttrs, Line, [{cons, LineNum, {tuple, _, _}, _} = Attrs]) -> handle_args(DefaultAttrs, Line, [{cons, LineNum, {tuple, _, _}, _} = Attrs]) ->
{concat_lists(DefaultAttrs, Attrs), {string, LineNum, ""}, {atom, Line, none}}; {concat_lists(DefaultAttrs, Attrs), {string, LineNum, ""}, {atom, Line, none}};
@ -317,6 +351,7 @@ guess_application(Dirname, Attr) when Dirname /= undefined ->
ok ok
end; end;
guess_application(undefined, {attribute, _, file, {Filename, _}}) -> guess_application(undefined, {attribute, _, file, {Filename, _}}) ->
put(filename, Filename),
Dir = filename:dirname(Filename), Dir = filename:dirname(Filename),
find_app_file(Dir); find_app_file(Dir);
guess_application(_, _) -> guess_application(_, _) ->

Loading…
Cancel
Save