最近項目需要一個日志工具來跟蹤程序便於調試和測試,為此研究了一下.NET日志工具,本文介紹了一些主流的日志框架並進行了對比.發表出來與大家分享.
綜述
所謂日志(這里指程序日志)就是用於記錄程序執行過程中的信息,以便開發、測試和支持人員在調試或測試時利用這種技術來快速分析和定位程序中的問題和缺陷。日志通常將程序執行中的信息以文本的形式寫入日志文件或將程序數據發送到監視器(比如說數據庫、遠端計算機、郵箱、網頁等)。高級一些的日志工具還支持對一些復雜的數據結構、調用棧、線程等進行實時監控和記錄。
大多數.NET的日志框架有着一些共同的概念和特性。根據作用來分主要有以下組件或概念:記錄器(Logger)、監視器/目標(Monitor/Target)、包裝器(Wrapper)、過濾器(Filter)、布局(Layout)、嚴重性級別(Severity)。
1.記錄器:日志的對象,可以同時連接一個或多個不同的監視器,記錄各種不同的消息和信息。
2.監視器:用於存儲和顯示日志消息的媒介,有多種存在形式。如一般的文本文件、數據庫、網絡、控制台、郵箱等。
3.包裝器:用於制定日志記錄的方式。如:同步/異步記錄,(出錯時)回滾記錄。
4.過濾器:用於根據嚴重性級別來過濾和忽略某類消息,只記錄特定級別的日志消息。
5.布局:用於格式化輸出。定義輸出項和輸出格式。
6.嚴重性級別:是對消息的分類,嚴重性級別表示消息的嚴重程度。也是過濾器的過濾依據。如:調試(DEBUG)、消息(INFO)、警告(WARN)、錯誤(ERROR)、嚴重錯誤(FATAL)嚴重性依次增強。
與上述對應的是一般的日志框架會提供的一些基本特性和功能:
1.記錄簡單的文本消息。
2.消息級別的過濾。
3.允許多個監視器。
4.記錄消息種類和會話。
5.根據時間或大小將文件分割。
6.通過配置文件來控制日志,與代碼分離。
當然還會有些高級功能,如線程的安全以及同步或異步,數據結構或對象的記錄,可視化的日志查看器和分析器等等。
現在,已經有很多成熟的.NET日志工具,免費的、收費的、開源的都有。 一些主流的日志工具和框架有:NLog、log4net、Enterprise Library、ObjectGuy Framework等。接下來主要介紹一下ObjectGuy Framework、log4net、NLog這三種日志框架。
ObjectGuy Framework
一種輕量級的.NET日志工具。能提供基本的日志特性並具有很好的擴展性。它是一種純代碼控制的日志工具,小巧便捷,語法簡單直接,很容易上手和使用。
ObjectGuy Framework中一般的logger只能對應一種監視器,而且都有相對應的類,這些類都是繼承自logger這個抽象基類。因此實例化一個logger很簡單,只要調用那個類即可。如TextWriterLogger、FileLogger、SerialSocketLogger分別對應監視器為控制台、文件、網絡的logger。當然如果你想綁定多個監視器,ObjectGuy提供了CompositeLogger這個類,並有相應的AddLogger方法可以將上述logger子類加入到CompositeLogger中與其綁定,這樣當CompositeLogger進行記錄時,其加入的普通logger都將同時自動記錄。ObjectGuy還有一個InsistentLogger類,顧名思義它是一個幫助的logger。當其綁定的主logger發生異常時,該InsistentLogger會自動啟動嘗試進行記錄。
ObjectGuy 中的消息分為7種嚴重性級別:Debug, Info, Status, Warning, Error, Critical, Fatal。默認級別為Debug。每一種級別都有對應的消息記錄方法LogXXX。消息過濾也很簡單,只要設置一下logger的SeverityThreshold的級別,那么所有級別低於SeverityThreshold的消息將被忽略。關於消息的格式化輸出,ObjectGuy提供了LogEntryFormatter類來制定相應的格式化。由於ObjectGuy中的所有特定logger都是繼承自Logger這一抽象類,因此構造自定義logger也很簡單,只要繼承該抽象類並重寫相應的方法即可。下圖為ObjectGuy中的類層次結構:
可以看出ObjectGuy是一個非常簡單易用的日志工具,它可以滿足基本的日志要求和特性而且有很好的擴展性。但是由於ObjectGuy非常簡潔,一些高級特性沒能被提供。其實ObjectGuy好比是編輯工具中的記事本,簡便、快捷。如果只是使用一些基本特性而對word又不是死磕的話,ObjectGuy還是一個非常不錯的選擇。(PS:ObjectGuy是一個付費工具,非商業版只要5美元。主頁:http://www.theobjectguy.com/dotnetlog/)
log4net
log4net是Apache上的一個開源項目,是基於非常成功的log4j(log for java)架構完成的。其實是log4j的.NET版本,但又結合了.NET的特性。log4net提供了很多功能,除了一些基本特性外,log4net支持配置文件控制。程序運行時只要修改配置文件就能對日志進行控制,實現和代碼的分離。另外log4net支持很多.NET框架,從1.0到4.0中的各種版本,同時也支持Mono(跨平台)。log4net中的監視器(Target)要比ObjectGuy豐富得多,有20種之多。
log4net中logger的使用不像ObjectGuy那樣直接。創建一個logger實例需要通過LogManager的GetLogger方法來完成。由於log4net中的logger是和類對應的(類級別日志,class-level logging),因此需要類名或類的類型typeof(類名)作為GetLogger的參數來獲取該類的logger的一個引用。相同的類名(指完整類層次名:namespace.className)指向同一個logger。在log4net中很特別的一點是logger的層次關系,一個logger可以有祖先logger和子logger,他們之間存在一些繼承關系。主要有兩方面:
1.嚴重性級別的繼承:log4net中有All、Debug、Info、Warn、Error、Fatal、Off七種級別,嚴重程度和優先級依次上升。若當前logger的級別為空(未賦值),則其繼承父logger的嚴重性級別。
2.監視器(log4net中稱Appender)的繼承:也叫監視器的可加性。當前logger的監視器如果為空,則繼承祖先logger的監視器。若不為空,則當前logger的監視器會自動添加祖先logger的監視器。也即祖先監視器會繼承給子監視器,這種特性依賴Additivity的值。其默認為真。可以看出與ObjectGuy不同的是,log4net中的logger可以任意綁定多個監視器,只要定義相應的Appender然后添加即可。
log4net中存在一個根logger(root logger),它是所有logger的祖先,嚴重性級別默認為Debug。其他的logger則會依據完整類層次名稱來區分祖先和后代關系。例如:對應於X.Y的logger的父親為對應於X的logger。當然只有這些logger被實例化之后這種關系才會生效。log4net中還提供對象呈現器(Object Renderers),它可以提供一種用戶自定義的對象呈現規則。當該對象被記錄時,對應的對象呈現器會自動觸發。
log4net的另一個特色是它的配置文件,配置文件可以像代碼一樣對logger進行各種設置。而且可以在程序運行時進行方便的進行修改從而得到需要的日志記錄。配置文件是XML格式,因此有很好的標記性,很容易書寫。配置文件的標簽包含大量API中logger相關的類。如:root(根logger)、logger、appender、layout、renderer、filter等。完全能夠像代碼一樣對程序中的日志進行設置和管理。
綜上所述,log4net能夠提供非常多的特性支持,相比ObjectGuy而言有過之無不及。而且有很多第三方的可視化日志查看器和分析器支持log4net使其更加直觀。然而log4net的架構也很復雜,因此使用起來沒有ObjectGuy那樣簡單直觀。另外由於log4net不能提供異步記錄,如果插入的代碼很多,勢必會影響應用程序的性能。(PS:log4net的更新非常緩慢,維護人員不多。從1.2.10版本到1.2.11版本花了4年時間(2006-2011)。主頁:http://logging.apache.org/log4net/)
NLog
NLog和log4net非常相似,都是開源工程,都支持.NET框架和跨平台,都有配置文件,都有豐富的監視器等等。可以說他們提供的特性絕大部分都是相同的。不過差別還是有的,下面主要講一下兩者的不同之處。
和log4net一樣,NLog中的logger也是類級別的。實例化一個logger除了像log4net一樣用LogManager.GetLogger("ClassName")也可以直接用LogManager.GetCurrentClassLogger()獲取當前類的logger。與log4net不同,NLog中的logger沒有層次結構,因此也不存在繼承等特征,所以NLog中logger的嚴重性級別和監視器(target)必須要定義。這一點跟ObjectGuy較像,簡單直觀。嚴重性級別上,NLog有Debug、Trace、Info、Warn、Error、Fatal六種。除了監視器,NLog中多了一層包裝器(Wrapper),顧名思義它是用來包裝監視器的。NLog提供了很多包裝器。如AsyncWrapper:異步包裝器,使logger可以異步地將記錄寫入包裝器里面的監視器,從而提高應用程序的響應速度,保證應用程序的性能不受太大影響;FallbackGroup:回滾組,當logger出現錯誤時回滾。由此可見NLog是支持異步和回滾的,這使得NLog的性能比log4net要好。至於配置文件方面,兩者只是標簽和屬性不同而已。
其實NLog更像是ObjectGuy和log4net的結合,既有ObjectGuy的簡單易用,又有log4net的絕大部分強大特性。而且NLog支持異步記錄,使得NLog的整體性能要優於log4net。NLog也有一些第三方圖形查看器和分析器。同時NLog更新頻繁,有很好的維護,應該是一個很不錯的選擇(個人推薦)。由於NLog使用起來非常方便(無論是通過代碼還是配置文件),這里不做過多介紹,詳細信息參看NLog主頁:http://nlog-project.org/。
最后附上一些主流.NET日志工具的綜合性能比較:
(PS:SmartInspect為純商業.NET日志工具,Enterprise Library為微軟推出的日志庫。)