OTP 事件管理器进程中的状态(不是处理程序!)
OTP 事件管理器进程(例如记录器)是否可以拥有自己的某种状态(例如日志记录级别)并基于它过滤/转换事件?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我还需要将一些状态放入 gen_event 本身,目前我最好的想法是使用进程字典(get/put)。处理程序在 gen_event 进程的上下文中调用,因此所有处理程序调用都将使用相同的进程字典。
是的,流程字典是邪恶的,但在这种情况下,它们似乎比替代方案(ets 表、状态服务器)邪恶的少。
I also have a need to put some state into the gen_event itself, and my best idea at the moment is to use the process dictionary (get/put). Handlers are invoked in the context of the gen_event process, so the same process dictionary will be there for all handler calls.
Yes, process dictionaries are evil, but in this case they seem less evil than alternatives (ets table, state server).
OTP 中包含的 gen_event 实现不提供添加状态的方法。
您可以扩展实现来实现此目的并使用您的实现而不是 gen_event。不过我建议不要这样做。
您想要添加到事件管理器的状态类型实际上属于事件处理程序,原因如下:
您可能希望在不同的处理程序中使用不同的级别,例如仅在控制台上显示错误,但将所有内容写入磁盘。
如果在管理器事件处理程序中根据获取所有未过滤的事件来更改事件级别,则可能会停止运行(事件的用途不仅仅是记录)。这可能会导致难以调试的问题。
如果您想要一个用于多个处理程序的事件管理器,所有处理程序都只获取过滤的事件,您可以通过使用两个管理器轻松实现这一点:一个用于未过滤的消息,另一个用于例如级别过滤的消息。然后为未过滤的事件安装一个处理程序,按级别过滤处理程序(简单),并将过滤后的事件传递给另一个管理器。所有只想获取已过滤消息的处理程序都可以注册到第二个管理器。
处理程序可以有自己的状态,在每个回调中传递,如下所示:
过滤可能如下所示(假设例如
{level N, Content}
事件):状态可以通过特殊事件、通过
gen_event:call\3,4
(最好)或通过handle_info处理的消息。有关详细信息,请参阅 Gen_Event 行为 和 gen_event(3)
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:
Filtering might look like this (assuming e.g.
{level N, Content}
events):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)
当您
start_link
一个gen_event
进程时(您应该始终通过主管来做这件事),您只需为新进程指定一个名称,如果您需要/希望它被注册。据我所知,无法使用该行为启动某种
状态
。当然,您可以在
gen_event
或简单的gen_server
顶部编写自己的行为。作为替代方案,您可以为每个调试级别使用单独的
gen_event
进程。或者您可以只过滤处理程序中的消息。
When you
start_link
agen_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 simplegen_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.