From 7df4c40d4e0dfc2287e45e623b69cb74f84fc655 Mon Sep 17 00:00:00 2001 From: Ulf Wiger Date: Thu, 21 Dec 2017 20:40:22 +0100 Subject: [PATCH] change flush default to true; add flush threshold --- README.md | 17 ++++++++++++++++- include/lager.hrl | 3 ++- src/error_logger_lager_h.erl | 3 ++- src/lager_file_backend.erl | 3 ++- src/lager_util.erl | 8 +++++++- 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f2d9be1..5858a8f 100644 --- a/README.md +++ b/README.md @@ -361,7 +361,7 @@ It is probably best to keep this number small. When the high-water mark is exceeded, lager can be configured to flush all event notifications in the message queue. This can have unintended consequences for other handlers in the same event manager (in e.g. the `error_logger'), as -events they rely on may be wrongly discarded. By default, this behavior is disabled, +events they rely on may be wrongly discarded. By default, this behavior is enabled, but can be controlled, for the `error_logger' via: ```erlang @@ -372,6 +372,21 @@ or for a specific sink, using the option: ```erlang {flush_queue, true | false} + +If `flush_queue` is true, a message queue length threshold can be set, at which +messages will start being discarded. The default threshold is `0`, meaning that +if `flush_queue` is true, messages will be discarded if the high-water mark is +exceeded, regardless of the length of the message queue. The option to control +the threshold is, for `error_logger`: + +```erlang +{error_logger_flush_threshold, 1000} +``` + +and for sinks: + +```erlang +{flush_threshold, 1000} ``` ### Sink Killer diff --git a/include/lager.hrl b/include/lager.hrl index 1be4f19..f190d92 100644 --- a/include/lager.hrl +++ b/include/lager.hrl @@ -122,7 +122,8 @@ %% count of dropped messages this second dropped = 0 :: non_neg_integer(), %% If true, flush notify messages from msg queue at overload - flush_queue = false :: boolean(), + flush_queue = true :: boolean(), + flush_threshold = 0 :: integer(), %% timer timer = make_ref() :: reference(), %% optional filter fun to avoid counting suppressed messages against HWM totals diff --git a/src/error_logger_lager_h.erl b/src/error_logger_lager_h.erl index fbae37f..6866496 100644 --- a/src/error_logger_lager_h.erl +++ b/src/error_logger_lager_h.erl @@ -73,7 +73,8 @@ set_high_water(N) -> -spec init(any()) -> {ok, #state{}}. init([HighWaterMark, GlStrategy]) -> Flush = lager_app:get_env(lager, error_logger_flush_queue, false), - Shaper = #lager_shaper{hwm=HighWaterMark, flush_queue = Flush, filter=shaper_fun(), id=?MODULE}, + FlushThr = lager_app:get_env(lager, error_logger_flush_threshold, 0), + Shaper = #lager_shaper{hwm=HighWaterMark, flush_queue = Flush, flush_threshold = FlushThr, filter=shaper_fun(), id=?MODULE}, Raw = lager_app:get_env(lager, error_logger_format_raw, false), Sink = configured_sink(), {ok, #state{sink=Sink, shaper=Shaper, groupleader_strategy=GlStrategy, raw=Raw}}. diff --git a/src/lager_file_backend.erl b/src/lager_file_backend.erl index 6d273af..1537b31 100644 --- a/src/lager_file_backend.erl +++ b/src/lager_file_backend.erl @@ -110,9 +110,10 @@ init(LogFileConfig) when is_list(LogFileConfig) -> %% probabably a better way to do this, but whatever [RelName, Level, Date, Size, Count, HighWaterMark, Flush, SyncInterval, SyncSize, SyncOn, CheckInterval, Formatter, FormatterConfig] = [proplists:get_value(Key, Config) || Key <- [file, level, date, size, count, high_water_mark, flush_queue, sync_interval, sync_size, sync_on, check_interval, formatter, formatter_config]], + FlushThr = proplists:get_value(flush_threshold, Config, 0), Name = lager_util:expand_path(RelName), schedule_rotation(Name, Date), - Shaper = lager_util:maybe_flush(Flush, #lager_shaper{hwm=HighWaterMark, id=Name}), + Shaper = lager_util:maybe_flush(Flush, #lager_shaper{hwm=HighWaterMark, flush_threshold = FlushThr, id=Name}), State0 = #state{name=Name, level=Level, size=Size, date=Date, count=Count, shaper=Shaper, formatter=Formatter, formatter_config=FormatterConfig, sync_on=SyncOn, sync_interval=SyncInterval, sync_size=SyncSize, check_interval=CheckInterval}, diff --git a/src/lager_util.erl b/src/lager_util.erl index b934a5c..ee26ad2 100644 --- a/src/lager_util.erl +++ b/src/lager_util.erl @@ -556,7 +556,7 @@ check_hwm(Shaper = #lager_shaper{lasttime = Last, dropped = Drop}) -> case Last of {M, S, N} -> %% still in same second, but have exceeded the high water mark - NewDrops = case Shaper#lager_shaper.flush_queue of + NewDrops = case should_flush(Shaper) of true -> discard_messages(Now, Shaper#lager_shaper.filter, 0); false -> @@ -575,6 +575,12 @@ check_hwm(Shaper = #lager_shaper{lasttime = Last, dropped = Drop}) -> {true, Drop, Shaper#lager_shaper{dropped = 0, mps=1, lasttime = Now}} end. +should_flush(#lager_shaper{flush_queue = true, flush_threshold = 0}) -> + true; +should_flush(#lager_shaper{flush_queue = true, flush_threshold = T}) -> + {_, L} = process_info(self(), message_queue_len), + L > T. + discard_messages(Second, Filter, Count) -> {M, S, _} = os:timestamp(), case Second of