From 73d286e2b0fdb5185503eb68ddfb01e5770ea6ab Mon Sep 17 00:00:00 2001 From: Sergey Prokhorov Date: Fri, 7 Jun 2013 22:15:08 +0400 Subject: [PATCH] Add `async_threshold_window` option. #147 --- README.md | 6 ++++-- src/lager.app.src | 5 ++++- src/lager_app.erl | 15 ++++++++++++++- src/lager_backend_throttle.erl | 11 ++++++----- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7c00447..0eb1711 100644 --- a/README.md +++ b/README.md @@ -154,11 +154,13 @@ polls its own mailbox size and toggles the messaging between synchronous and asynchronous depending on mailbox size. ```erlang -{async_threshold, 20} +{async_threshold, 20}, +{async_threshold_window, 5} ``` This will use async messaging until the mailbox exceeds 20 messages, at which -point synchronous messaging will be used. +point synchronous messaging will be used, and switch back to asynchronous, when +size reduces to `20 - 5 = 15`. If you wish to disable this behaviour, simply set it to 'undefined'. It defaults to a low number to prevent the mailbox growing rapidly beyond the limit and causing diff --git a/src/lager.app.src b/src/lager.app.src index 5c88a0b..63f35ce 100644 --- a/src/lager.app.src +++ b/src/lager.app.src @@ -53,6 +53,9 @@ %% How many messages per second to allow from error_logger before we start dropping them {error_logger_hwm, 50}, %% How big the gen_event mailbox can get before it is switched into sync mode - {async_threshold, 20} + {async_threshold, 20}, + %% Switch back to async mode, when gen_event mailbox size decrease from `async_threshold' + %% to async_threshold - async_threshold_window + {async_threshold_window, 5} ]} ]}. diff --git a/src/lager_app.erl b/src/lager_app.erl index 148742f..d169f80 100644 --- a/src/lager_app.erl +++ b/src/lager_app.erl @@ -42,7 +42,20 @@ start(_StartType, _StartArgs) -> {ok, undefined} -> undefined; {ok, Threshold} when is_integer(Threshold), Threshold >= 0 -> - _ = supervisor:start_child(lager_handler_watcher_sup, [lager_event, lager_backend_throttle, Threshold]), + DefWindow = erlang:trunc(Threshold * 0.2), % maybe 0? + ThresholdWindow = + case application:get_env(lager, async_threshold_window) of + undefined -> + DefWindow; + {ok, Window} when is_integer(Window), Window < Threshold, Window >= 0 -> + Window; + {ok, BadWindow} -> + error_logger:error_msg( + "Invalid value for 'async_threshold_window': ~p~n", [BadWindow]), + throw({error, bad_config}) + end, + _ = supervisor:start_child(lager_handler_watcher_sup, + [lager_event, lager_backend_throttle, [Threshold, ThresholdWindow]]), ok; {ok, BadThreshold} -> error_logger:error_msg("Invalid value for 'async_threshold': ~p~n", [BadThreshold]), diff --git a/src/lager_backend_throttle.erl b/src/lager_backend_throttle.erl index 34ff46e..14573b0 100644 --- a/src/lager_backend_throttle.erl +++ b/src/lager_backend_throttle.erl @@ -31,12 +31,13 @@ -record(state, { hwm, + window_min, async = true }). -init(Hwm) -> +init([Hwm, Window]) -> lager_config:set(async, true), - {ok, #state{hwm=Hwm}}. + {ok, #state{hwm=Hwm, window_min=Hwm - Window}}. handle_call(get_loglevel, State) -> @@ -48,12 +49,12 @@ handle_call(_Request, State) -> handle_event({log, _Message},State) -> {message_queue_len, Len} = erlang:process_info(self(), message_queue_len), - case {Len > State#state.hwm, State#state.async} of - {true, true} -> + case {Len > State#state.hwm, Len < State#state.window_min, State#state.async} of + {true, _, true} -> %% need to flip to sync mode lager_config:set(async, false), {ok, State#state{async=false}}; - {false, false} -> + {_, true, false} -> %% need to flip to async mode lager_config:set(async, true), {ok, State#state{async=true}};