Dot-Net

使用 EventSource 記錄 ETW 失去事件的風險

  • June 22, 2013

我正在檢測我的 .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作為有效負載值傳遞時收到的消息。

該類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 的行為符合您的預期。

引用自:https://stackoverflow.com/questions/17246261