2010-10-14 224 views
5

我的(本地,windows/mono)應用程序將重要事件記錄到文本文件。如果發生突然的崩潰/故障/強制退出,則不應將數據保留爲未寫入(儘可能)。因此,我目前使用的是簡單的追加到文本文件的方法:什麼是記錄最好的方法?

Public Shared Sub LogAppEvent(ByVal EventData As String) 
    Dim Config As ConfigHandler = ConfigHandler.GetSingleton() 
    Dim AppLog As New IO.StreamWriter(Config.GetUserFilesRootDir() & ConfigOptions.AppLogName, True) 
    AppLog.WriteLine(String.Format("[{0}] {1}", Date.Now.ToString(), EventData)) 
    AppLog.Close() 
End Sub 

這是高度優化的,但記錄的事件是非常罕見的。你會建議搬到System.Diagnostics日誌類嗎?

或者,也許你會建議另一種解決方案?

回答

14

如果這樣的超級基本方法是適合您的需要功能足夠了,你能堅持下來。但是,你可能會問自己幾個問題,以確保:

  • 是否有可能要由多個線程同時記錄的事件?這個功能是不是線程安全的

  • 是錯誤通知需要?

  • 有沒有式增長,沒有自動刪除日誌文件的風險?

  • 你會從更廣泛的日誌中受益,讓您有關於事件導致了一個錯誤的詳細信息?

  • 你會從更多有關錯誤的詳細受益(堆棧跟蹤,異常詳細信息等)

  • 是否在多臺計算機上的程序運行?如果是這樣,日誌如何做到?

  • 是否有工具的任何需要/價值,幫助分析日誌文件(無論是單獨或尋找模式,例如在許多日誌文件常見的錯誤)?

如果您認爲您有其他需求,也有一些免費的日誌框架,如NLog or log4net,可以幫助記錄更詳細的日誌,還有一些商業產品,如GIBRALTARSmartInspect可用,可以幫助與日誌管理和分析。

+1

+1爲線程安全點,但只有主線程推送日誌事件。感謝您的全面回答。 – 2010-10-14 18:08:34

2

Nloglog4Net是在.NET項目記錄流行的選擇。

+0

兩者都是很好的建議。我喜歡他們的配置。 – 2010-10-14 15:52:31

+0

log4Net規則! – user279521 2010-10-14 20:12:53

1

是的,你可以考慮System.Diagnostics。只要您不寫大量事件,Windows事件日誌的優勢在於管理員有一個位置可以查找所有應用程序中的所有事件。

下面是一些VB.NET代碼,可以幫助你,你應該決定走這條路:

Imports System.Diagnostics 

Public Function WriteToEventLog(ByVal Entry As String, _ 
    Optional ByVal AppName As String = "VB.NET Application", _ 
    Optional ByVal EventType As _ 
    EventLogEntryType = EventLogEntryType.Information, _ 
    Optional ByVal LogName As String = "Application") As Boolean 

'************************************************************* 
'PURPOSE: Write Entry to Event Log using VB.NET 
'PARAMETERS: Entry - Value to Write 
'   AppName - Name of Client Application. Needed 
'    because before writing to event log, you must 
'    have a named EventLog source. 
'   EventType - Entry Type, from EventLogEntryType 
'    Structure e.g., EventLogEntryType.Warning, 
'    EventLogEntryType.Error 
'   LogName: Name of Log (System, Application; 
'    Security is read-only) If you 
'    specify a non-existent log, the log will be 
'    created 

'RETURNS: True if successful, false if not 

'EXAMPLES: 
'1. Simple Example, Accepting All Defaults 
' WriteToEventLog "Hello Event Log" 

'2. Specify EventSource, EventType, and LogName 
' WriteToEventLog("Danger, Danger, Danger", "MyVbApp", _ 
'      EventLogEntryType.Warning, "System") 
' 
'NOTE:  EventSources are tightly tied to their log. 
'   So don't use the same source name for different 
'   logs, and vice versa 
     '****************************************************** 

     Dim objEventLog As New EventLog() 

     Try 
      'Register the App as an Event Source 
      If Not objEventLog.SourceExists(AppName) Then 

       objEventLog.CreateEventSource(AppName, LogName) 
      End If 

      objEventLog.Source = AppName 

      'WriteEntry is overloaded; this is one 
      'of 10 ways to call it 
      objEventLog.WriteEntry(Entry, EventType) 
      Return True 
     Catch Ex As Exception 
      Return False 

     End Try 

    End Function 
+0

感謝您的詳細幫助。我會研究在我的應用程序中包括這個。 – 2010-10-14 18:09:10

+0

System.Diagnostics可以寫入除事件日誌之外的其他位置。 – 2010-12-08 19:49:51

13

如前所述,NLOG和log4net的都是很好的日誌框架。正如Jeff在上面提到的,System.Diagnostics也是一個合理的選擇(不僅僅是記錄到EventLog)。試圖給我的答案增加一些價值,而不是僅僅喋喋不休地說,你可以使用TraceSources和免費的Ukadc.Diagnostics library from codeplex來增強你的System.Diagnostics日誌記錄。

使用TraceSources,您可以創建「命名記錄器」,類似於您可以在NLog和log4net中執行的操作。這些TraceSources可以配置爲在某些級別上記錄(每個TraceSource都不相同),並可以將它們發送到不同的目標(TraceListeners)。所有TraceSources都可以登錄到同一個監聽器,或者一些可以登錄到某些監聽器,而其他監聽器則可以登錄到其他監聽器。任何TraceSource也可以發送到多個TraceListeners。

這裏是您如何在代碼中使用TraceSources(假設TraceSource「abc」已在app.config文件中配置爲記錄「Info」和更高優先級的消息並且已配置爲登錄到文件「log」。文本」)。

public class MyClass 
{ 
    static TraceSource ts = new TraceSource("abc"); //Common idiom for NLog and log4net, not sure if as common for TraceSource 

    public void Func1(int x) 
    { 
    ts.Information("Entering Func1"); 
    ts.Verbose("x = {0}", x); //Won't log if "abc" is configured to log Info and HIGHER messgaes 
    ts.Information("Exiting Func1"); 
    } 
} 

一個巨大Ukadc.Diagnostics的利益,在「普通」 TraceSources,是可以配置的NLOG/log4net的風格輸出格式,所以你可以有在什麼領域在日誌產出和顯示更多的控制格式。

三件事情是非常有用的,從NLOG/log4net的不可用在System.Diagnostics程序是:

  1. 能夠自動記錄通話網站的信息(方法/功能)

  2. 附加日誌上下文(GDC - 全局日誌記錄屬性,MDC - NLog/log4net說法中的線程日誌記錄屬性)。 System.Diagnostics的確有Trace.CorrelationManager.LogicalOperationStack,它與NDC類似。

  3. Hierarichal伐木工。

分層記錄器意味着你可以配置一個「祖先」記錄器和任何「後代」記錄器將繼承這些設置。例如,假設您有一個完全(名稱空間)限定類型名稱爲Namespace1.Namespace2.Class的類。使用NLog/log4net,您可以爲「Namespace1」配置日誌信息(級別,目標),並且如果您根據Namespace1中任何類型的完全限定名稱請求記錄器,它將繼承Namespace1的設置。您可以通過查看Castle implemented their TraceSource-based logging抽象如何使用TraceSources實現與此類似的功能。特別是,看看Initialize函數。在TraceSource的自定義小包裝器中工作起來非常容易(作爲一個優點),使得TraceSources的配置更容易一些,因爲您不必單獨配置每個TraceSource。請注意,如果沒有找到實際的祖先,您可以通過配置一個名爲「」的TraceSource並在城堡方案中添加一些代碼,默認爲「」配置,從而輕鬆添加具有「根」配置的功能。例如,您可以配置「*」來登錄,比如說Verbose,然後特定配置某些TraceSources(按類或名稱空間)關閉或處於不同的級別。如果沒有hierarichal記錄器,要使用TraceSources執行相同的操作,則需要配置每個TraceSource以詳細記錄「詳細」。

雖然我介紹了很多關於類和名稱空間的記錄器,但NLog,log4net和TraceSources都允許您將記錄器名稱定義爲任意字符串。因此,在冷定義由功能區域的記錄器的層次結構,而不是命名空間/類:

Database 
Database.Connect 
Database.Query 
Database.Update 
Database.SQL 
Amazon 
Amazon.Books 
Amazon.Books.Fiction 
Amazon.Books.Nonfiction 
Amazon.Electronics 
Amazon.Electronics.Video 
Amazon.Electronics.Music 
Amazon.Electronics.Computer 

所以,你可以打開「亞馬遜」的日誌記錄和所有亞馬遜的東西日誌(而無需顯式配置每「孩子」TraceSource)和數據庫的東西不會。或者,您可以關閉Amazon並關閉Amazon.Electronics,並且只有Amazon.Books(和兒童)才能登錄。

最後,如果你使用NLog或log4net,值得一提的是NLog剛剛發佈了一個新版本NLog 2.0(測試版)。

+0

感謝您的全面回答=)但是,如果我開始使用NLog,我的應用程序大小几乎會乘以5)這是一個非常輕的應用程序,因此它不需要*高級日誌記錄。但是,謝謝你的偉大答案,我將用它來做另一個項目。 – 2010-10-16 19:19:56

+1

很好的答案。非常全面,並有一個代碼示例。好樣的!這個信息正是我正在尋找的。 – 2010-11-29 18:04:04

0

我使用公共變量和計時器將新行添加到txt文件。

E.g.

Public Class Form1 

    Public WriteToLog = "" 

    Dim LogFilePath As String = My.Application.Info.DirectoryPath & "\applog.txt" 

.... 

    Public Function Log_to_txt(ByVal text As String) 

     Dim CurDate As String 
     CurDate = Format(Now, "General Date") 

     WriteToLog = WriteToLog & "[" & CurDate & "] " & text & vbCrLf 

     Return True 

    End Function 

... 

Log_to_txt("Application started...") 

... 

    Private Sub WriteToLogTimer_Tick(sender As Object, e As EventArgs) Handles WriteToLogTimer.Tick 

     Dim CatchLog As String = WriteToLog 

     WriteToLog = "" 

     Try 

      My.Computer.FileSystem.WriteAllText(LogFilePath, CatchLog, True) 

     Catch ex As IOException 

     End Try 

    End Sub 
相關問題