21

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

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

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

以下是 Microsoft 谈论错过事件的可能原因的一个来源: 关于事件跟踪

他们在那里列出了丢失事件的这些可能原因

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

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

  • 对于实时日志,实时消费者没有足够快地消费事件或完全不存在,然后支持文件被填满。如果在记录事件时停止并启动事件日志服务,则会出现这种情况。用户无法控制这些丢失的事件。

  • 记录到文件时,磁盘速度太慢,无法跟上记录速度。

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

所以每当我的有效载荷中有一个字符串时,我必须通过一些截断器传递它?我是否也需要手动避免生成“太快”的事件(这怎么可能)?

Microsoft Patterns and Practices 应该引导我们找到好的......模式和实践......所以也许我只是在这里遗漏了一些东西。

更新:

显然,在消费应用程序中有一些“事件太快”条件的通知。我今天第一次收到这个:

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

然后在关闭会话时:

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

更新2:

Enterprise Library Developers Guide描述了我刚才提到的行为。

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

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

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

更新 3:

我收到的“丢失事件”警告与缓冲区溢出无关,事实证明这是您将 nullstring作为有效负载值传递时收到的消息。

4

3 回答 3

8

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

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

默认情况下,调用“WriteEvent”方法不会引发错误(它们会默默地丢弃事件)。这是因为在大多数情况下,用户认为日志记录并不“宝贵”,并且不希望日志记录失败导致程序崩溃。然而,对于那些日志记录是“宝贵”的应用程序,如果它失败了,调用者希望做出反应,如果 WriteEvent 失败,设置“throwOnEventWriteErrors”将导致抛出异常。请注意,EventWrite 成功并不一定意味着事件到达其目的地,只是写入它的操作没有失败。

不幸的是,最后一句包含一个警告购买者,但如果您查看源代码,EventSource您会发现操作系统调用的底层返回代码用于为NoFreeBuffersEventTooBig(和其他错误)抛出不同的异常。

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

于 2014-08-21T07:13:55.020 回答
7

有一件事是在上面的讨论中有两个重要的点没有说清楚。

  1. 所有与丢弃事件相关的问题都与 ETW(Windows 事件跟踪)有关,而不是 EventSource。从逻辑上讲,EventSources 与 EventListeners 对话,并且有一个内置的侦听器可以转发给 ETW。显然,当您谈论丢弃事件时,链中任何链接的约束都会影响流经链的数据。因此,保证完全可靠性的一种方法是使用 EventListener,它不使用 ETW,而是直接转到您希望数据去往的任何地方。我相信(语义日志记录应用程序块)有这样的监听器。

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

所以总而言之,EventSource 默认支持可靠事件,ETW 默认不支持,但可以使其支持,但通常,ETW 的默认设置非常好。

于 2016-03-21T16:42:00.103 回答
-1

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

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

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

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

于 2014-01-17T10:30:22.077 回答