2008-11-24 83 views
14

我最近在部署Windows服務期間遇到問題。四臺電腦沒有造成任何問題,但第五次嘗試啓動服務失敗的原因是異常。異常堆棧跟蹤寫入到事件日誌,所以我雖然它應該很容易找出原因:寫入事件日誌條目的最佳方式是什麼?

protected override void OnStart(string[] args) 
{ 
    EventLog.WriteEntry("Starting service", EventLogEntryType.Information); 

    try 
    { 
     //... 
     base.OnStart(args); 
    } 
    catch (Exception ex) 
    { 
     EventLog.WriteEntry("Service can not start. Stack trace:" + ex.StackTrace, EventLogEntryType.Error); 
     Stop(); 
     return; 
    } 

    EventLog.WriteEntry("Service started", EventLogEntryType.Information);   
} 

但很可惜,沒有信息被不斷寫入日誌。我終於追溯到正在寫入的第一個日誌條目。它引發了一個異常,因爲應用程序事件日誌滿了最近的條目,並被配置爲只覆蓋超過7天的條目。

考慮到我無法更改應用程序事件日誌的配置,寫入事件日誌的最佳做法是什麼?我應該如何將EventLog.WriteEntry放在try塊中,如果是的話,我應該如何處理這個異常(寫入事件日誌可能是個壞主意),我應該檢查我的OnStart方法中的事件日誌狀態,或者你有更好的建議嗎?

回答

2

我認爲日誌記錄異常是您最好吞嚥異常的罕見情況之一。在大多數情況下,你不希望你的應用程序失敗。

但是,爲什麼你自己寫自己的日誌代碼呢?使用像NLog或Log4Net這樣的框架!這些也可以像我剛剛說的那樣吞下異常,但只需更改配置,就可以將日誌記錄輸出重定向到其他位置(文件,消息框等)。這使得解決這樣的問題變得更容易。

+15

寫入事件日誌不是「自己寫日誌代碼」。 – MusiGenesis 2008-11-24 10:58:57

+0

@MusiGenesis:請解釋一下。對於我來說,編寫日誌特定的異常處理是編寫代碼,例如Log4Net或NLog已經做得更好。我沒有理由寫另一個日誌框架。 – Mendelt 2008-11-24 11:10:49

11

使用log4net的

使用的log4net的好處是,你可以檢查記錄,並與更靈活地控制它比你自己的代碼中佔了。

如果您正在登錄到事件日誌,並且看到問題並且沒有事件日誌條目,那麼您總是可以切換到文件appender日誌並已經看到它正在工作......然後它會告訴您它是與事件日誌有關。

log4net也是防禦性的,如果它沒有寫入日誌條目,它不會崩潰你的程序。所以你不會看到這種情況發生(所以你不會有你的日誌文件,但你的程序將會運行,並且你可能已經指定了第二種日誌記錄方法來獲取日誌文件)。

log4net的文檔中的鍵位是這樣的:

[log4net的]是一個盡力而爲和故障停機記錄系統。

通過失敗停止,我們的意思是log4net不會在運行時拋出意外的異常,可能會導致您的應用程序崩潰。如果出於任何原因,log4net會拋出一個未捕獲的異常(除了可能拋出的ArgumentException和ArgumentNullException外),請發送電子郵件至[email protected]郵件列表。未捕獲的異常被視爲需要立即關注的嚴重錯誤。

此外,log4net在其指定的輸出流未打開,不可寫入或變滿時,將不會恢復到System.Console.Out或System.Console.Error。這避免了由於記錄失敗而導致用戶的終端氾濫,從而破壞了另外的工作程序。但是,log4net會向System.Console.Error和System.Diagnostics.Trace輸出一條消息,指出無法執行日誌記錄。

(我的重點)

對於大多數的事情,有可能做的更好比你會圖書館。最好的事情是永遠不要重新發明,log4net可以解決.Net中的日誌記錄,並會讓你的生活更輕鬆。

+2

實際上,log4net確實有能力導致應用程序崩潰(至少是緊湊的框架/ Windows移動應用程序) - 有點。使用log4net的UDP appender會使ActiveSync(將設備連接到PC)崩潰。我在演示中瞭解到這一點,我們失去了一個巨大的聯繫。 – MusiGenesis 2008-11-24 11:14:33

+0

我認爲在Windows服務中使用log4net和Windows事件日誌是完全合理的。用於非常高級別的事件的Windows事件日誌,即系統管理員可以快速查看的事件日誌;和一個更詳細的log4net日誌,它提供了關於你的代碼活動的豐富細節。 – 2013-12-05 09:46:13

2

研究利用Logging App Block

企業庫日誌記錄應用程序塊簡化了常用日誌記錄功能的實現。開發人員可以使用日誌程序塊將信息寫入不同的位置:

  • 事件日誌
  • 的電子郵件
  • 數據庫
  • 消息隊列
  • 的文本文件
  • WMI事件
  • 使用應用程序塊擴展點的自定義位置
4
System.Diagnostics.EventLog log = 
    new System.Diagnostics.EventLog("YourLogNameHere"); 
log.ModifyOverflowPolicy(
    System.Diagnostics.OverflowAction.OverwriteAsNeeded, 0); 

這應該解決您的溢出問題。一旦配置正確,事件日誌通常非常可靠。在使用事件日誌時,我曾經添加一個簡單的寫入文本文件的緊急備份記錄器(這需要大約5分鐘的時間)。它從來沒有被召喚過。

3

你不能只使用ServiceBase類已經提供的默認事件日誌機制嗎?如果你的服務沒有啓動,會自動向事件日誌中寫入一個條目,說明如此(使用堆棧跟蹤)。

除此之外,關於log4net(或任何其他盡力而爲的日誌系統)的評論,我認爲這取決於你想達到的目標。

在您使用log4net的示例中(或者對ServiceBase的eventlogging的內置支持)很可能是可以的。

但是,在某些情況下,即使發生錯誤並且該事實不能記錄在某處也是一個問題。例如,假設一個認證或授權系統。如果您無法成功和可靠地記錄該密碼,例如由於憑證錯誤而導致密碼驗證失敗,則可能不允許繼續(如果密碼驗證成功,則同樣如此BTW)。

因此,有時您需要知道日誌記錄嘗試失敗的時間並自行處理。 這當然是有限制的(雞 - 雞蛋問題),你做什麼是高度特定於特定的應用程序或場景。

0

讓我們退後一步,在這裏:

系統事件日誌有提醒系統管理員,有與系統上的一些問題。您應該允許服務開始失敗。這將在系統錯誤日誌中顯示,並報告「服務控制管理器」的來源。這意味着系統管理員將知道失敗。

接下來,如果您需要排除故障,那麼您應該在程序的頂層將異常記錄到磁盤上的文件。您還應該重新推出它們,以便服務啓動失敗。

然後,您可以識別系統事件日誌中的任何問題,並將失敗的時間交叉引用到應用程序日誌中。

相關問題