diff options
Diffstat (limited to 'deps/lager/src/lager_backend_throttle.erl')
-rw-r--r-- | deps/lager/src/lager_backend_throttle.erl | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/deps/lager/src/lager_backend_throttle.erl b/deps/lager/src/lager_backend_throttle.erl new file mode 100644 index 0000000..90b9c40 --- /dev/null +++ b/deps/lager/src/lager_backend_throttle.erl @@ -0,0 +1,105 @@ +%% Copyright (c) 2011-2013 Basho Technologies, Inc. All Rights Reserved. +%% +%% This file is provided to you under the Apache License, +%% Version 2.0 (the "License"); you may not use this file +%% except in compliance with the License. You may obtain +%% a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, +%% software distributed under the License is distributed on an +%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%% KIND, either express or implied. See the License for the +%% specific language governing permissions and limitations +%% under the License. + +%% @doc A simple gen_event backend used to monitor mailbox size and +%% switch log messages between synchronous and asynchronous modes. +%% A gen_event handler is used because a process getting its own mailbox +%% size doesn't involve getting a lock, and gen_event handlers run in their +%% parent's process. + +-module(lager_backend_throttle). + +-include("lager.hrl"). + +-behaviour(gen_event). + +-export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, + code_change/3]). + +%% +%% Allow test code to verify that we're doing the needful. +-ifdef(TEST). +-define(ETS_TABLE, async_threshold_test). +-define(TOGGLE_SYNC(), test_increment(sync_toggled)). +-define(TOGGLE_ASYNC(), test_increment(async_toggled)). +-else. +-define(TOGGLE_SYNC(), true). +-define(TOGGLE_ASYNC(), true). +-endif. + +-record(state, { + sink :: atom(), + hwm :: non_neg_integer(), + window_min :: non_neg_integer(), + async = true :: boolean() + }). + +init([{sink, Sink}, Hwm, Window]) -> + lager_config:set({Sink, async}, true), + {ok, #state{sink=Sink, hwm=Hwm, window_min=Hwm - Window}}. + + +handle_call(get_loglevel, State) -> + {ok, {mask, ?LOG_NONE}, State}; +handle_call({set_loglevel, _Level}, State) -> + {ok, ok, State}; +handle_call(_Request, State) -> + {ok, ok, State}. + +handle_event({log, _Message},State) -> + {message_queue_len, Len} = erlang:process_info(self(), message_queue_len), + case {Len > State#state.hwm, Len < State#state.window_min, State#state.async} of + {true, _, true} -> + %% need to flip to sync mode + ?TOGGLE_SYNC(), + lager_config:set({State#state.sink, async}, false), + {ok, State#state{async=false}}; + {_, true, false} -> + %% need to flip to async mode + ?TOGGLE_ASYNC(), + lager_config:set({State#state.sink, async}, true), + {ok, State#state{async=true}}; + _ -> + %% nothing needs to change + {ok, State} + end; +handle_event(_Event, State) -> + {ok, State}. + +handle_info(_Info, State) -> + {ok, State}. + +%% @private +terminate(_Reason, _State) -> + ok. + +%% @private +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +-ifdef(TEST). +test_get(Key) -> + get_default(ets:lookup(?ETS_TABLE, Key)). + +test_increment(Key) -> + ets:insert(?ETS_TABLE, + {Key, test_get(Key) + 1}). + +get_default([]) -> + 0; +get_default([{_Key, Value}]) -> + Value. +-endif. |