From 4b5260c4524688b545cc12da6baa2dfa4f2afec9 Mon Sep 17 00:00:00 2001 From: Mark Allen Date: Tue, 29 Mar 2016 10:46:27 -0500 Subject: [PATCH] Overhaul start up and add killer config 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. --- src/lager_app.erl | 106 +++++++++++++++++++++------------------------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/src/lager_app.erl b/src/lager_app.erl index 5ed1415..136caa5 100644 --- a/src/lager_app.erl +++ b/src/lager_app.erl @@ -29,7 +29,7 @@ start/2, start_handler/3, stop/1, - boot/0]). + boot/1]). -define(FILENAMES, '__lager_file_backend_filenames'). -define(THROTTLE, lager_backend_throttle). @@ -53,21 +53,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) -> @@ -119,14 +117,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) -> @@ -147,24 +153,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, _} -> @@ -174,17 +162,6 @@ start_error_logger_handler(_, HWM, {ok, WhiteList}) -> [] end. - -%% `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), @@ -193,12 +170,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, [])), @@ -209,6 +185,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), @@ -222,35 +200,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) ->