OTP事件管理器进程中的状态(不是处理程序!)

时间:2010-10-20 09:09:19

标签: erlang gen-event

OTP事件管理器进程(例如记录器)是否具有自己的某种状态(例如日志记录级别)并基于它来过滤/转换事件?

3 个答案:

答案 0 :(得分:1)

OTP中包含的gen_event实现没有提供添加状态的方法。 您可以扩展实现以实现此目的,并使用您的实现而不是gen_event。不过我会反对它。

您想要添加到事件管理器的状态实际上属于事件处理程序,原因如下:

  • 您可能希望在不同的处理程序中使用不同的级别,例如仅在控制台上显示错误,但将所有内容写入磁盘。

  • 如果事件级别将在管理器事件处理程序中更改,具体取决于获取所有未过滤的事件可能会停止运行(事件的用途多于仅记录日志)。这可能导致难以调试问题。

  • 如果您希望多个处理程序的事件管理器只能获得过滤事件,您可以通过拥有两个管理器轻松实现此目的:一个用于未过滤的消息,另一个用于例如级别过滤的消息。然后在未过滤的处理程序中安装一个处理程序,按级别(简单)过滤处理程序,并将过滤的事件传递给另一个管理器。所有只想过滤消息的处理程序都可以注册到第二个管理器。

处理程序可以拥有自己的状态,每次回调都会传递,如:

Module:handle_event(Event, State) -> Result

过滤可能如下所示(假设例如{level N, Content}个事件):

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

可以通过特殊事件,gen_event:call\3,4(最好)或handle_info处理的消息来更改状态。

有关详细信息,请参阅Gen_Event Behaviourgen_event(3)

答案 1 :(得分:1)

我还需要将一些状态放入gen_event本身,我最好的想法是使用进程字典(get / put)。处理程序在gen_event进程的上下文中调用,因此所有处理程序调用都将使用相同的进程字典。

是的,流程词典是邪恶的,但在这种情况下,它们似乎不如替代品(ets table,state server)邪恶。

答案 2 :(得分:0)

当你start_link gen_event进程 - 你应该经常通过主管做的事情 - 时,如果你需要/希望它被注册,你只需指定新进程的名称。 据我所知,没有办法使用这种行为发起某种state

当然,您可以在gen_event或简单gen_server之上编写自己的行为。

作为替代方案,您可以为每个调试级别使用单独的gen_event进程。 或者您只需过滤处理程序中的消息。