Skip to content

Commit

Permalink
Overhaul start up and add killer config
Browse files Browse the repository at this point in the history
Previously, configuration would come from application:get_env/3 or
proplists:get_value/3. Now we standardize on a single format
for retrieving values from the environment or from a proplist.
  • Loading branch information
Mark Allen committed Apr 7, 2016
1 parent 35e10cf commit bd3c1ec
Showing 1 changed file with 49 additions and 56 deletions.
105 changes: 49 additions & 56 deletions src/lager_app.erl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
start_handler/3,
configure_sink/2,
stop/1,
boot/0]).
boot/1]).

%% The `application:get_env/3` compatibility wrapper is useful
%% for other modules
Expand Down Expand Up @@ -58,21 +58,19 @@ start_throttle(Sink, Threshold, Window) ->
[Sink, ?THROTTLE, [Threshold, Window]]),
ok.

determine_async_behavior(_Sink, {ok, undefined}, _Window) ->
ok;
determine_async_behavior(_Sink, undefined, _Window) ->
ok;
determine_async_behavior(_Sink, {ok, Threshold}, _Window) when not is_integer(Threshold) orelse Threshold < 0 ->
determine_async_behavior(_Sink, Threshold, _Window) when not is_integer(Threshold) orelse Threshold < 0 ->
error_logger:error_msg("Invalid value for 'async_threshold': ~p~n",
[Threshold]),
throw({error, bad_config});
determine_async_behavior(Sink, {ok, Threshold}, undefined) ->
determine_async_behavior(Sink, Threshold, undefined) ->
start_throttle(Sink, Threshold, erlang:trunc(Threshold * 0.2));
determine_async_behavior(_Sink, {ok, Threshold}, {ok, Window}) when not is_integer(Window) orelse Window > Threshold orelse Window < 0 ->
determine_async_behavior(_Sink, Threshold, Window) when not is_integer(Window) orelse Window > Threshold orelse Window < 0 ->
error_logger:error_msg(
"Invalid value for 'async_threshold_window': ~p~n", [Window]),
throw({error, bad_config});
determine_async_behavior(Sink, {ok, Threshold}, {ok, Window}) ->
determine_async_behavior(Sink, Threshold, Window) ->
start_throttle(Sink, Threshold, Window).

start_handlers(_Sink, undefined) ->
Expand Down Expand Up @@ -124,14 +122,22 @@ clean_up_config_checks() ->

interpret_hwm(undefined) ->
undefined;
interpret_hwm({ok, undefined}) ->
undefined;
interpret_hwm({ok, HWM}) when not is_integer(HWM) orelse HWM < 0 ->
interpret_hwm(HWM) when not is_integer(HWM) orelse HWM < 0 ->
_ = lager:log(warning, self(), "Invalid error_logger high water mark: ~p, disabling", [HWM]),
undefined;
interpret_hwm({ok, HWM}) ->
interpret_hwm(HWM) ->
HWM.

maybe_install_sink_killer(_Sink, undefined, _ReinstallTimer) -> ok;
maybe_install_sink_killer(Sink, HWM, undefined) -> maybe_install_sink_killer(Sink, HWM, 5000);
maybe_install_sink_killer(Sink, HWM, ReinstallTimer) when is_integer(HWM) andalso is_integer(ReinstallTimer)
andalso HWM >= 0 andalso ReinstallTimer >= 0 ->
_ = supervisor:start_child(lager_handler_watcher_sup, [Sink, lager_manager_killer,
[HWM, ReinstallTimer]]);
maybe_install_sink_killer(_Sink, HWM, ReinstallTimer) ->
error_logger:error_msg("Invalid value for 'killer_hwm': ~p or 'killer_reinstall_after': ~p", [HWM, ReinstallTimer]),
throw({error, bad_config}).

start_error_logger_handler({ok, false}, _HWM, _Whitelist) ->
[];
start_error_logger_handler(_, HWM, undefined) ->
Expand All @@ -152,24 +158,6 @@ start_error_logger_handler(_, HWM, {ok, WhiteList}) ->
throw({error, bad_config})
end,

%% Conditionally start the high watermark killer.
case application:get_env(lager, killer_hwm) of
undefined -> ok;
{ok, undefined} -> ok;
{ok, KillerHWM} when is_integer(KillerHWM), KillerHWM >= 0 ->
KillerReinstallAfter = case application:get_env(lager, killer_reinstall_after) of
undefined -> 5000;
{ok, undefined} -> 5000;
{ok, V} when is_integer(V), V >= 0 -> V;
{ok, BadKillerReinstallAfter} ->
error_logger:error_msg("Invalid value for 'cooldown': ~p~n",
[BadKillerReinstallAfter]),
throw({error, bad_config})
end,
_ = supervisor:start_child(lager_handler_watcher_sup,
[?DEFAULT_SINK, lager_manager_killer,
[KillerHWM, KillerReinstallAfter]])
end,

case supervisor:start_child(lager_handler_watcher_sup, [error_logger, error_logger_lager_h, [HWM, GlStrategy]]) of
{ok, _} ->
Expand All @@ -189,16 +177,6 @@ start_error_logger_handler(_, HWM, {ok, WhiteList}) ->
end,
Handlers.

%% `determine_async_behavior/3' is called with the results from either
%% `application:get_env/2' and `proplists:get_value/2'. Since
%% `application:get_env/2' wraps a successful retrieval in an `{ok,
%% Value}' tuple, do the same for the result from
%% `proplists:get_value/2'.
wrap_proplist_value(undefined) ->
undefined;
wrap_proplist_value(Value) ->
{ok, Value}.

configure_sink(Sink, SinkDef) ->
lager_config:new_sink(Sink),
ChildId = lager_util:make_internal_sink_name(Sink),
Expand All @@ -207,12 +185,11 @@ configure_sink(Sink, SinkDef) ->
{gen_event, start_link,
[{local, Sink}]},
permanent, 5000, worker, dynamic}),
determine_async_behavior(Sink,
wrap_proplist_value(
proplists:get_value(async_threshold, SinkDef)),
wrap_proplist_value(
proplists:get_value(async_threshold_window, SinkDef))
determine_async_behavior(Sink, proplists:get_value(async_threshold, SinkDef),
proplists:get_value(async_threshold_window, SinkDef)
),
maybe_install_sink_killer(Sink, proplists:get_value(killer_hwm, SinkDef),
proplists:get_value(killer_reinstall_after, SinkDef)),
start_handlers(Sink,
proplists:get_value(handlers, SinkDef, [])),

Expand All @@ -223,6 +200,8 @@ configure_extra_sinks(Sinks) ->
lists:foreach(fun({Sink, Proplist}) -> configure_sink(Sink, Proplist) end,
Sinks).

get_env(Application, Key) ->
get_env(Application, Key, undefined).
%% R15 doesn't know about application:get_env/3
get_env(Application, Key, Default) ->
get_env_default(application:get_env(Application, Key),
Expand All @@ -236,35 +215,49 @@ get_env_default({ok, Value}, _Default) ->
start(_StartType, _StartArgs) ->
{ok, Pid} = lager_sup:start_link(),
SavedHandlers = boot(),
_ = boot('__all_extra'),
_ = boot('__traces'),
clean_up_config_checks(),
{ok, Pid, SavedHandlers}.

boot() ->
%% Handle the default sink.
determine_async_behavior(?DEFAULT_SINK,
application:get_env(lager, async_threshold),
application:get_env(lager, async_threshold_window)),
get_env(lager, async_threshold),
get_env(lager, async_threshold_window)),

maybe_install_sink_killer(?DEFAULT_SINK, get_env(lager, killer_hwm),
get_env(lager, killer_reinstall_after)),

start_handlers(?DEFAULT_SINK,
get_env(lager, handlers, ?DEFAULT_HANDLER_CONF)),


lager:update_loglevel_config(?DEFAULT_SINK),

SavedHandlers = start_error_logger_handler(
application:get_env(lager, error_logger_redirect),
interpret_hwm(application:get_env(lager, error_logger_hwm)),
application:get_env(lager, error_logger_whitelist)
get_env(lager, error_logger_redirect),
interpret_hwm(get_env(lager, error_logger_hwm)),
get_env(lager, error_logger_whitelist)
),

_ = lager_util:trace_filter(none),
SavedHandlers.

%% Now handle extra sinks
configure_extra_sinks(get_env(lager, extra_sinks, [])),
boot('__traces') ->
_ = lager_util:trace_filter(none),
ok = add_configured_traces();

ok = add_configured_traces(),
boot('__all_extra') ->
configure_extra_sinks(get_env(lager, extra_sinks, []));

clean_up_config_checks(),
boot(?DEFAULT_SINK) -> boot();
boot(Sink) ->
AllSinksDef = get_env(lager, extra_sinks, []),
boot_sink(Sink, lists:keyfind(Sink, 1, AllSinksDef)).

SavedHandlers.
boot_sink(Sink, {Sink, Def}) ->
configure_sink(Sink, Def);
boot_sink(Sink, false) ->
configure_sink(Sink, []).

stop(Handlers) ->
lists:foreach(fun(Handler) ->
Expand Down

0 comments on commit bd3c1ec

Please sign in to comment.