This chapter should be read in conjunction with
In OTP, an event manager is a named object to which events can be sent. An event could be, for example, an error, an alarm or some information that should be logged.
In the event manager, zero, one or several event handlers are installed. When the event manager is notified about an event, the event will be processed by all the installed event handlers. For example, an event manager for handling errors can by default have a handler installed which writes error messages to the terminal. If the error messages during a certain period should be saved to a file as well, the user adds another event handler which does this. When logging to file is no longer necessary, this event handler is deleted.
An event manager is implemented as a process and each event handler is implemented as a callback module.
The event manager essentially maintains a list of
The callback module for the event handler writing error messages to the terminal could look like:
-module(terminal_logger).
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init(_Args) ->
{ok, []}.
handle_event(ErrorMsg, State) ->
io:format("***Error*** ~p~n", [ErrorMsg]),
{ok, State}.
terminate(_Args, _State) ->
ok.
The callback module for the event handler writing error messages to a file could look like:
-module(file_logger).
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init(File) ->
{ok, Fd} = file:open(File, read),
{ok, Fd}.
handle_event(ErrorMsg, Fd) ->
io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
{ok, Fd}.
terminate(_Args, Fd) ->
file:close(Fd).
The code is explained in the next sections.
To start an event manager for handling errors, as described in the example above, call the following function:
gen_event:start_link({local, error_man})
This function spawns and links to a new process, an event manager.
The argument,
If the name is omitted, the event manager is not registered.
Instead its pid must be used. The name could also be given
as
Here is an example using the shell on how to start an event manager and add an event handler to it:
1> gen_event:start({local, error_man}). {ok,<0.31.0>} 2> gen_event:add_handler(error_man, terminal_logger, []). ok
This function sends a message to the event manager registered as
init(_Args) ->
{ok, []}.
Here,
init(File) ->
{ok, Fd} = file:open(File, read),
{ok, Fd}.
3> gen_event:notify(error_man, no_reply). ***Error*** no_reply ok
The event is made into a message and sent to the event manager.
When the event is received, the event manager calls
In
handle_event(ErrorMsg, State) ->
io:format("***Error*** ~p~n", [ErrorMsg]),
{ok, State}.
In
handle_event(ErrorMsg, Fd) ->
io:format(Fd, "***Error*** ~p~n", [ErrorMsg]),
{ok, Fd}.
4> gen_event:delete_handler(error_man, terminal_logger, []). ok
This function sends a message to the event manager registered as
For
terminate(_Args, _State) ->
ok.
For
terminate(_Args, Fd) ->
file:close(Fd).
When an event manager is stopped, it will give each of
the installed event handlers the chance to clean up by calling
If the event manager is part of a supervision tree, no stop
function is needed. The event manager will automatically be
terminated by its supervisor. Exactly how this is done is
defined by a
An event manager can also be stopped by calling:
> gen_event:stop(error_man). ok
If the gen_event should be able to receive other messages than
events, the callback function
handle_info({'EXIT', Pid, Reason}, State) ->
..code to handle exits here..
{ok, NewState}.
The code_change method also has to be implemented.
code_change(OldVsn, State, Extra) ->
..code to convert state (and more) during code change
{ok, NewState}