使用EventSource从ETW日志记录丢失事件的风险

我使用EventSource类来检测我的.NET 4.5应用程序以发出ETW事件。 我们的目标是能够捕获一些事件(错误级别事件)以进行错误记录。

在做了一些阅读和测试之后,我担心这种错误记录方法的可靠性,特别是关于丢失或丢失事件的可能性。 如果我的错误日志记录不工作,我需要关闭应用程序(在我的情况下,它是不安全的,它与未报告的错误运行)。 当使用ETW和EventSource ,我怎么能确定我的错误得到了正确的记录?

显然,答案的一部分将取决于听事件的内容。 就我而言,我打算使用最新MS企业库中的“语义记录应用程序块”。

这里有一个微软谈到错过事件可能原因的来源:关于事件追踪

他们列出了失踪事件的可能原因

  • 总事件大小大于64K。 这包括ETW头和数据或有效载荷。 由于事件大小是由应用程序配置的,用户无法控制这些丢失的事件。

  • ETW缓冲区大小小于总事件大小。 由于事件大小是由记录事件的应用程序配置的,用户无法控制这些丢失的事件。

  • 对于实时日志记录来说,实时消费者不会消耗足够快的事件,或者完全不存在,然后备份文件就会被填满。 如果事件日志服务停止并且在记录事件时启动,则可能会导致这种情况。 用户无法控制这些丢失的事件。

  • 在记录到文件时,磁盘速度太慢以至于无法跟上记录速率。

  • 为了查看这些问题是否使用EventSource类以某种方式缓解(例如,它是否以某种方式截断了大型有效内容),我做了一些测试。 我尝试记录长字符串,并且失败了30,000到35,000个字符(与64KB最大事件有效载荷一致)。 它只是默默无闻地告诉我太大的字符串,在我的语义记录应用程序块日志中根本没有发生任何事件。 之前和之后的事件都像往常一样写。

    所以任何时候我在我的有效载荷中有一个字符串,我必须通过一些截断器? 我是否需要手动避免“太快”生成事件(以及如何实现这一点)?

    微软的模式和实践应该引导我们做出很好的...模式和实践......所以也许我只是在这里错过了一些东西。

    更新:

    很明显,消费应用程序中有一些关于“事件太快”情况的通知。 我今天第一次收到这个消息:

    级别:警告,消息:由于缓冲区溢出或跟踪会话中的模式同步延迟,某些事件将会丢失:Microsoft-SemanticLogging-Etw-svcRuntime

    然后在结束会议时:

    级别:警告,消息:在跟踪会话“Microsoft-SemanticLogging-Etw-svcRuntime”中检测到1事件丢失。

    UPDATE2:

    “企业图书馆开发人员指南”介绍了我刚刚提到的行为。

    您应该监视由语义日志记录应用程序块生成的日志消息,以了解是否有缓冲区已满并且已丢失消息的任何指示。 例如,具有事件ID 900和901的日志消息表明接收器的内部缓冲区溢出; 在进程外场景中,事件ID 806和807表明ETW缓冲区溢出。 您可以修改接收器的缓冲配置选项,以降低缓冲区溢出典型工作负载的可能性。

    我的问题仍然存在,我可以使用语义日志记录,同时确保我的应用程序不会运行,如果错误被丢弃? 正常的跟踪事件可能会被删除...

    我目前的想法是使用老式的日志记录技术在单独的类中记录“关键”错误,并通过ETW管道保留较少的关键错误(以及调试类型事件)。 这真的不会太糟......如果我找不到更好的建议,我可能会将其作为解决方案发布。

    更新3:

    我收到的“缺失事件”警告与缓冲区溢出无关,事实证明,如果您将空string作为有效负载值传递,则会出现此消息。


    EventSource类有两个版本,一个包含在.NET Framework中,另一个包含在NuGet包Microsoft EventSource Library中。 我假设你使用NuGet包,因为它包含更新的代码。

    EventSource基类的构造函数有一个重载,它带有一个布尔参数throwOnEventWriteErrors和以下文档(NuGet包版本1.0.26.0):

    默认情况下调用'WriteEvent'方法不会抛出错误(他们会默默放弃事件)。 这是因为在大多数情况下,用户认为日志记录不“珍贵”,并且不希望记录失败导致程序崩溃。 然而,对于其中记录是“珍贵”,如果失败呼叫方希望作出反应,制定“throwOnEventWriteErrors”这些应用程序会导致如果WriteEvent未能抛出异常。 请注意,EventWrite成功的事实并不一定意味着事件只有在写入操作没有失败的情况下才会到达目的地。

    不幸的是,最后一个句子中包含一个买者自负,但如果你看看源代码, EventSource ,你可以看到,从操作系统调用底层的返回代码被用于抛出不同的异常NoFreeBuffersEventTooBig (和其他错误)。

    所以如果你打开throwOnEventWriteErrors你会得到异常,如果EventSource类无法将事件传递给ETW。 但是,如果ETW由于其他原因而失败,则不会得到任何异常,但是如果确保您的ETW通道配置正确,那么应该很少发生。 但是,由于您无法容忍丢失任何错误事件,因此您应该测试极端错误情况,以确保ETW按照您的预期行事。


    有一件事在上面的讨论中没有明确说明两个重点。

  • 与下降事件相关的所有问题都与ETW(Windows事件跟踪)有关,而不是EventSource。 这是EventSOurces在逻辑上与EventListeners的对话,并且有内置的侦听器转发给ETW。 很明显,当你谈论掉线事件时,链中任何链接的约束都会影响链中的数据流动。 因此,保证完全可靠性的一种方法是使用不使用ETW的EventListener,而是直接将数据发送到任何地方。 我相信(语义记录应用程序块)有这样的监听器。

  • ETW已成功用于可靠地转发事件,但您必须在上述限制范围内生活(事件的大小必须保持<64K,并且必须控制事件速率。请注意,如果速率为你会知道这一点,因为WriteEvent会失败,所以你可以重试(暂停后),从而做一些完全可靠的事情(以减慢程序速度为代价)。注意这种数据丢失不是如果你真的在谈论错误(这不应该以巨大的速度发生),并且如果它们发生率很高,它们很可能是多余的(同样的事情很快就会发生),这个有趣的问题。

  • 因此,总而言之,EventSource默认支持可靠的事件,ETW默认情况下不支持它,但可以支持它,但是通常ETW的默认值不是很好。


    尝试查看语义日志(MS企业库6)http://msdn.microsoft.com/en-us/library/dn440729(v=pandp.60).aspx

    您可以使用事件源并创建侦听器将日志记录到事件查看器或文件或数据库(或创建自定义解决方案)

    更新:即使在IoC场景中,我也会捕获事件ID 806/807。 在一个拦截器中,有一部分代码实例化了我的EventSource类:如果你错过了第一个实例的引用,所有其他实例在构造函数上失败并且在写入事件时引发事件ID 806/807

    为了记录大数据,可以应用消息拆分技术

    链接地址: http://www.djcxy.com/p/90855.html

    上一篇: Risk of missing events from ETW logging with EventSource

    下一篇: app purchase by id purchase live