Enterprise Library 2.0 中的 Logging Application Block 在1.0版本中是Logging and Instrumentation Application Block,因?yàn)榘阎攸c(diǎn)放在了日志記錄上,所以改名為L(zhǎng)ogging Application Block。Logging Application Block提供了統(tǒng)一的日志記錄功能,它支持將日志寫(xiě)入到多種目的地中,比如:1、數(shù)據(jù)庫(kù);2、文本文件;3、Email;4、消息隊(duì)列;5、WMI event;6、事件日志;7、自定義區(qū)域(For Example:XML File)等等。
?? Logging Application Block 提供了統(tǒng)一的接口用于將日志寫(xiě)入到任何指定的目的地,我們不需要在代碼中指定日志信息該寫(xiě)到什么地方,而是在配置文件中設(shè)定我們什么情況
下寫(xiě)日志以及將日志信息寫(xiě)到什么地方,這也就意味著操作員可以和我們開(kāi)發(fā)人員一樣不通過(guò)修改代碼來(lái)改變?nèi)罩居涗浶袨椤K鼘?duì)于我們程序開(kāi)發(fā)有以下幾點(diǎn)好處:
1、可以使我們的應(yīng)用程序中的日志記錄方法保持一致;
2、正是因?yàn)樗峁┮恢碌慕Y(jié)構(gòu)模型,很大程度上方便了我們開(kāi)發(fā)人員對(duì)其的學(xué)習(xí);
3、很好的解決了應(yīng)用程序中的日志問(wèn)題;
4、可擴(kuò)展,我們可以自定義日志信息的過(guò)濾程序以及格式化日志信息的程序
... ...
?? 相對(duì)于上一個(gè)版本,Logging Application Block 2.0作出了下列改變:
1、LogEntry對(duì)象現(xiàn)在可以屬于一個(gè)或多個(gè)類(lèi)別(category);
2、2.0版本中我們可以自定義過(guò)濾器,在Logging Application Block 將日志信息發(fā)送給監(jiān)聽(tīng)器(trace listeners)之前就將該信息過(guò)濾掉,過(guò)濾器支持我們根據(jù)事件的類(lèi)別和(或)優(yōu)先級(jí)來(lái)過(guò)濾事件,我們可以定制符合自己需要的標(biāo)準(zhǔn)的過(guò)濾器來(lái)過(guò)濾事件;
3、你可以在代碼中通過(guò)查詢(xún)過(guò)濾器來(lái)判斷當(dāng)前事件是否需要被記錄日志,這樣就大大減少了我們?nèi)罩居涗浟浚梢杂行У奶岣邞?yīng)用程序的性能。
?? 下面我們就來(lái)說(shuō)一下Logging Application Block的使用方法,首先需要添加對(duì)下面三個(gè)程序集的引用:
using?Microsoft.Practices.EnterpriseLibrary.Logging;
using?Microsoft.Practices.EnterpriseLibrary.Logging.ExtraInformation;
using?Microsoft.Practices.EnterpriseLibrary.Logging.Filters;

?????? 和前面幾個(gè)Block一樣,在使用之前還是先說(shuō)一下配置方法,首先用配置工具代開(kāi)我們程序的App.Config/Web.Config,然后選中Application右鍵,New-->Logging Application Block,如下圖:

這時(shí)你會(huì)發(fā)現(xiàn),在新建的Logging Application Block節(jié)點(diǎn)下自動(dòng)出現(xiàn)了Filters,Category Source,Special Source,Trace Listeners,Formatters這樣的幾個(gè)節(jié)點(diǎn),如下:

????? 我下面按照我配置的順序來(lái)說(shuō)一下每個(gè)節(jié)點(diǎn)的作用,首先是Formatters,它用于指定日志信息的格式,如下圖,我們?cè)贔ormatters節(jié)點(diǎn)下創(chuàng)建一個(gè)Text Formatter,如下:

然后我們可以編輯它的模板,編輯我們要顯示的信息,如下:

我們還可以配置Binary Formatter和自定義的Formatter ,這里不在多說(shuō)了。
?????? Formatter配置好了以后,我們就可以來(lái)配置Trace Listeners了,Enterprise Library 2.0 提供了七種Trace Listeners,分別用于將日志信息記錄到特定的目的地中,下面我們就來(lái)配置一個(gè)Flat File Trace Listener ,如下:

??????? 使用Flat File Trace Listener后,記錄的日志信息就輸出到指定的文本文件中,所以我們要指定輸出的文本文件的路徑,默認(rèn)在Bin/Debug目錄下;同時(shí)我們需指定該Listener的Formatter,Name等屬性。如果我們配置的是一個(gè)DataBase Listener,我們則要在數(shù)據(jù)庫(kù)中建立相應(yīng)的表,并創(chuàng)建一個(gè)用于插入日志信息的存儲(chǔ)過(guò)程。

Trace Listeners 配置好之后就可以開(kāi)始配置Category Source,我們新建一個(gè)Category Source,命名為General,指定其SourceLevel為All,如下:

之后,我們可以對(duì)剛添加的Category Source添加一個(gè)或多個(gè)Trace Listener,本文中,我們將上面配置的SHY52O Formatter加進(jìn)來(lái),

???????? 如上圖,在RefrenceTraceListener中選擇SHY520 Listeners就可以了。
???????? 最后我們來(lái)看一下如何配置過(guò)濾器(Filters),Enterprise Library 2.0 中提供了三種默認(rèn)的Filters,分別是:Category Filter ,Log Enable Filter和Priority Filter,我們以Category Filter為例來(lái)配置:

然后可以修改過(guò)濾器名稱(chēng)和過(guò)濾規(guī)則:

這里面我們可以選擇過(guò)濾的模式,過(guò)濾模式有兩種:
1、Allow All Categories Except those explicitly denied below
2、Deny All Categories Except those explicitly allowed below
根據(jù)我們需要選擇好過(guò)濾模式,然后添加需要過(guò)濾的類(lèi)別,點(diǎn)擊OK按鈕即可完成Category Filter的配置。
??????? 關(guān)于Logging Application Block 的介紹和配置部分就說(shuō)到這里,下一篇我們?cè)趤?lái)介紹Logging Application Block的使用方法以及自定義Formatter和Listener的方法。
上一篇中我們介紹了如何去配置Logging Application Block,本文將主要介紹Logging Application Block 的基本操作以及Formatter和Trace Listeners 的自定義方法,首先我們來(lái)看如何將一個(gè)事件日志寫(xiě)入到一個(gè)文本文件中。
??? 假設(shè)我們按照上一篇的操作配置了Logging Application Block,那么配置文件中的信息如下:
??<loggingConfiguration?name="Logging?Application?Block"?tracingEnabled="true"
????defaultCategory="General"?logWarningsWhenNoCategoriesMatch="true">
????<listeners>
??????<add?fileName="trace.log"?header="----------------------------------------"
????????footer="----------------------------------------"?formatter="SHY520?Formatter"
????????listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData,?

Microsoft.Practices.EnterpriseLibrary.Logging,?Version=2.0.0.0,?Culture=neutral,?PublicKeyToken=null"
????????traceOutputOptions="None"?type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener,?

Microsoft.Practices.EnterpriseLibrary.Logging,?Version=2.0.0.0,?Culture=neutral,?PublicKeyToken=null"
????????name="SHY520?Listeners"?/>
??????<add?source="Enterprise?Library?Logging"?formatter="Text?Formatter"
????????log="Application"?machineName=""?listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData,?

Microsoft.Practices.EnterpriseLibrary.Logging,?Version=2.0.0.0,?Culture=neutral,?PublicKeyToken=null"
????????traceOutputOptions="None"?type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener,?

Microsoft.Practices.EnterpriseLibrary.Logging,?Version=2.0.0.0,?Culture=neutral,?PublicKeyToken=null"
????????name="Formatted?EventLog?TraceListener"?/>
????</listeners>
????<formatters>
??????<add?template="Timestamp:?{timestamp} Message:?{message} Category:?{category} Priority:?{priority} EventId:?

{eventid} Severity:?{severity} Title:{title} Machine:?{machine} Application?Domain:?{appDomain} Process?Id:?

{processId} Process?Name:?{processName} Win32?Thread?Id:?{win32ThreadId} Thread?Name:?{threadName} Extended?Properties:?

{dictionary({key}?-?{value} )}"
????????type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter,?Microsoft.Practices.EnterpriseLibrary.Logging,?Version=2.0.0.0,?

Culture=neutral,?PublicKeyToken=null"
????????name="Text?Formatter"?/>
??????<add?template="Timestamp:?{timestamp} Message:?{message} Category:?{category} Priority:?{priority} EventId:?

{eventid} Severity:?{severity} Title:{title} Machine:?{machine} Application?Domain:?{appDomain} Process?Id:?

{processId} Process?Name:?{processName} Win32?Thread?Id:?{win32ThreadId} Thread?Name:?{threadName} Extended?Properties:?

{dictionary({key}?-?{value} )}"
????????type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter,?Microsoft.Practices.EnterpriseLibrary.Logging,?Version=2.0.0.0,?

Culture=neutral,?PublicKeyToken=null"
????????name="SHY520?Formatter"?/>
????</formatters>
????<logFilters>
??????<add?categoryFilterMode="AllowAllExceptDenied"?type="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.CategoryFilter,?

Microsoft.Practices.EnterpriseLibrary.Logging,?Version=2.0.0.0,?Culture=neutral,?PublicKeyToken=null"
????????name="Category?Filter"?/>
????</logFilters>
????<categorySources>
??????<add?switchValue="All"?name="General">
????????<listeners>
??????????<add?name="SHY520?Listeners"?/>
????????</listeners>
??????</add>
????</categorySources>
????<specialSources>
??????<allEvents?switchValue="All"?name="All?Events"?/>
??????<notProcessed?switchValue="All"?name="Unprocessed?Category"?/>
??????<errors?switchValue="All"?name="Logging?Errors?&?Warnings">
????????<listeners>
??????????<add?name="Formatted?EventLog?TraceListener"?/>
????????</listeners>
??????</errors>
????</specialSources>
??</loggingConfiguration>
下面我們來(lái)看如何將日志寫(xiě)入到文本文件:
????????[TestMethod]
????????public?void?DoLog()

????????
{
????????????//創(chuàng)建一個(gè)日志條目
????????????LogEntry?log?=?new?LogEntry();
????????????//指定該日志所屬類(lèi)別
????????????log.Categories.Add("General");
????????????//日志標(biāo)題
????????????log.Title?=?"SHY520's?Tests";
????????????log.Message?=?"there?is?log?information";
????????????//優(yōu)先級(jí)
????????????log.Priority?=?0;

????????????Logger.Write(log);
????????}
????? 上面的代碼中,我們?yōu)樵撊罩局付ㄋ鶎兕?lèi)別為General,在配置文件中我們可以看到General這個(gè)類(lèi)別使用的Trace Listener是SHY520 Listeners,SHY520 Listeners是一個(gè)Flat File Trace Listener,它指定了我們的日志信息輸出的地方(trace.log),我用的測(cè)試項(xiàng)目,運(yùn)行測(cè)試后,該文件在TestResult/out目錄中,如果是一般的Web項(xiàng)目或Consle項(xiàng)目,該文件則在Bin/Debug目錄下,下面我們來(lái)看一下輸出的日志信息:

上圖中,我們可以看到我們?cè)诔绦蛑杏涗浀囊恍┤罩拘畔ⅲ覀冞€可以記錄一些額外的信息,這些信息是鍵值對(duì)應(yīng)的,在1.0版本中我們用Hashtable,這里我們用的是一個(gè)泛型的Dictionary類(lèi)型,代碼如下:
????????[TestMethod]
????????public?void?LoggEntry()

????????
{
????????????LogEntry?log?=?new?LogEntry();
????????????//事件ID
????????????log.EventId?=?2000;
????????????//日志優(yōu)先級(jí)
????????????log.Priority?=?2;
????????????log.Message?=?"Test?LogEntry?2";

????????????//日志類(lèi)別
????????????ICollection<string>?coll?=?new?List<string>();
????????????coll.Add("General");
????????????log.Categories?=?coll;

????????????//添加額外信息
????????????Dictionary<string,?object>?dic?=?new?Dictionary<string,?object>();
????????????dic.Add("name",?"SHY520");
????????????dic.Add("sex","男");
????????????dic.Add("age",?"22");

????????????log.ExtendedProperties?=?dic;
????????????//寫(xiě)入日志
????????????Logger.Write(log);
????????}
然后運(yùn)行測(cè)試,在TestResult/Out目錄下的trace.log文件中就能看到我們?cè)诔绦蛑刑砑拥念~外信息了。

下面我們來(lái)介紹一下過(guò)濾器的用法:
實(shí)現(xiàn)方法很簡(jiǎn)單,這里我們假設(shè)我們已經(jīng)按照上一篇文章中的方法配置好了一個(gè)Category Filter,在Category Filter中我們可以設(shè)置要過(guò)濾掉哪種類(lèi)別的事件日志,具體實(shí)現(xiàn)方式有兩種,如下:
方法一:
????????[TestMethod]
????????public?void?TestFilter1()

????????
{
????????????LogEntry?logEntry?=?new?LogEntry();
????????????logEntry.Priority?=?2;
????????????logEntry.Categories.Add("General");

????????????//ShouldLog()方法根據(jù)Filter配置返回是否需要記錄日志
????????????if?(Logger.GetFilter<CategoryFilter>().ShouldLog(logEntry.Categories))

????????????
{
????????????????//TODO:記錄日志
????????????????Logger.Write(logEntry);
????????????}
????????}
方法二:
????????[TestMethod]
????????public?void?TestFilter2()

????????
{
????????????LogEntry?logEntry?=?new?LogEntry();
????????????logEntry.Priority?=?2;
????????????logEntry.Categories.Add("General");

????????????if?(Logger.ShouldLog(logEntry))

????????????
{
????????????????Logger.Write(logEntry);
????????????}
????????}
??????? 關(guān)于事件日志的過(guò)濾就說(shuō)到這里,下面我們來(lái)看看如何創(chuàng)建一個(gè)自定義的Trace Listener,首先我們新建一個(gè)類(lèi)(MyListener),并且繼承與CustomTraceListener,同時(shí)不要忘了在為這個(gè)新建的類(lèi)加上[ConfigurationElementType(typeof(CustomTraceListenerData))]的Attribute,最后重寫(xiě)基類(lèi)的三個(gè)方法,在每個(gè)方法中加入自己需要的邏輯既可。完整的類(lèi)的代碼如下:
using?System;
using?System.Collections.Generic;
using?System.Text;
using?Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using?Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using?Microsoft.Practices.EnterpriseLibrary.Logging;
using?Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;

namespace?Enterprise_Library_2


{
????[ConfigurationElementType(typeof(CustomTraceListenerData))]
????public?class?MyListener?:?CustomTraceListener

????
{
????????public?override?void??TraceData(System.Diagnostics.TraceEventCache?eventCache,?string?source,?System.Diagnostics.TraceEventType?eventType,?int?id,?

object?data)

????????
{
????????????if?(data?is?LogEntry?&&?this.Formatter?!=?null)

????????????
{
????????????????this.WriteLine(this.Formatter.Format(data?as?LogEntry));
????????????}
????????????else

????????????
{
????????????????this.WriteLine(data.ToString());
????????????}
????????}


????????public?override?void?Write(string?message)

????????
{
????????????//TODO:添加自己所需的邏輯
????????}

????????public?override?void?WriteLine(string?message)

????????
{
????????????//TODO:添加自己所需的邏輯
????????}
????}
}
然后我們?cè)谂渲肨race Listener的時(shí)候選擇Custom Trace Listener就可以了。
接下來(lái)我們來(lái)看看如何自定義Formatter,實(shí)現(xiàn)的方法和上面類(lèi)似,首先新建一個(gè)類(lèi)MyFormatter,繼承ILogFormatter接口,同時(shí)加上[ConfigurationElementType(typeof(CustomFormatterData))]的Attribute,完整的代碼如下:
using?System;
using?System.Collections.Generic;
using?System.Text;
using?System.Collections.Specialized;
using?Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using?Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using?Microsoft.Practices.EnterpriseLibrary.Logging;
using?Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;

namespace?Enterprise_Library_2


{
????[ConfigurationElementType(typeof(CustomFormatterData))]
????public?class?MyFormatter?:?ILogFormatter????

????
{
????????public?MyFormatter(NameValueCollection?nv)

????????
{
????????????//注意:構(gòu)造函數(shù)的參數(shù)必須是NameValueCollection類(lèi)型的
????????}

????????public?string?Format(LogEntry?log)

????????
{
????????????string?result?=?string.Empty;

????????????//TODO:此處添加我們個(gè)性化的Formatter邏輯

????????????return?result;
????????}
????}
}
到這里,關(guān)于Logging Application Block的有關(guān)問(wèn)題已經(jīng)都簡(jiǎn)單的介紹了一下,有遺漏錯(cuò)誤的地方,請(qǐng)指正,謝謝!
希望對(duì)初學(xué)者有所幫助,同時(shí)也歡迎Enterprise Library學(xué)習(xí)者一起共同交流經(jīng)驗(yàn)。
凡是有該標(biāo)志的文章,都是該blog博主Caoer(草兒)原創(chuàng),凡是索引、收藏
、轉(zhuǎn)載請(qǐng)注明來(lái)處和原文作者。非常感謝。