Let's say I have several versions of the handler gen_eventand you want to change them while the program is running:
-module(logger_all).
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init(_Args) ->
{ok, []}.
handle_event({Severity, ErrorMsg}, State) ->
io:format("***~p*** ~p~n", [Severity, ErrorMsg]),
{ok, State}.
terminate(_Args, _State) ->
ok.
-module(logger_errors_only).
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init(_Args) ->
{ok, []}.
handle_event({error, ErrorMsg}, State) ->
io:format("***Error*** ~p~n", [ErrorMsg]),
{ok, State}.
handle_event({_, ErrorMsg}, State) ->
{ok, State}. %% ignore everything except errors
terminate(_Args, _State) ->
ok.
Obviously, I can switch them by removing one handler and adding another:
log_errors_only() ->
gen_event:delete_handler(error_man, logger_all, []),
gen_event:add_handler(error_man, logger_errors_only, []).
But this leaves the possibility of a race condition; if error_manan event is received only at the wrong time, it will not be recorded. Or, if I change the order of actions, it will be recorded twice, which is also undesirable. How can I make sure it is processed exactly once?
In this case, I can just have one handler and maintain the logging level as State, but suppose this is not acceptable.