views:

48

answers:

2

Can an OTP event manager process (e.g. a logger) have some state of its own (e.g. logging level) and filter/transform events based on it?

+1  A: 

The gen_event implementation as contained in the OTP does no provide means for adding state. You could extend the implementation to achieve this and use your implementation instead of gen_event. However I would advise against it.

The kind of state you want to add to the event manager belongs really in the event handler for several reasons:

  • You might want to use different levels in different handlers, e.g. only show errors on the console but write everything to the disk.

  • If the event level would be changed in the manager event handlers depending on getting all unfiltered events might cease to function (events have more uses than just logging). This might lead to hard to debug problems.

  • If you want a event manager for multiple handlers that all only get filtered events you can easily achieve this by having two managers: one for unfiltered messages and one for e.g. level filtered messages. Then install a handler to the unfiltered one, filter in the handler by level (easy) and pass on the filtered events to the other manager. All handlers that only want to get filtered messages can be registered to the second manager.

The handlers can have their own state that gets passed on every callback like:

Module:handle_event(Event, State) -> Result

Filtering might look like this (assuming e.g. {level N, Content} events):

handle_event({level, Lvl, Content}, State#state{max_level=Max}) when Lvl >= Max ->
     gen_event:notify(filtered_man, Content);

The State can be changed either by special events, by gen_event:call\3,4 (preferably) or by messages handled by handle_info.

For details see Gen_Event Behaviour and gen_event(3)

Peer Stritzinger
`gen_event` behaviour is for event handlers, not event managers.
Alexey Romanov
Sorry I was misreading your question. I'll edit the answer
Peer Stritzinger
Obviously if there are handlers relying on getting all events untransformed, you wouldn't filter/transform events in the manager. I am only interested in the case where _all_ handlers do need filtered messages. Yes, I thought the solution close to the one described in your third point might be necessary (except with a `gen_server` and not another event manager in front) and was looking if there is a better way.
Alexey Romanov
A: 

When you start_link a gen_event process - thing that you should always do via a supervisor -, you can merely specify a name for the new process, if you need/want it to be registered. As far as I can see, there's no way to initiate a state of some sort using that behaviour.

Of course, you can write your own behaviour, on the top of a gen_event or of a simple gen_server.

As an alternative, you might use a separate gen_event process for each debugging level. Or you can just filter the messages in the handlers.

Roberto Aloi