NLog文章系列——入門教程(上)
作者:Jaros?aw Kowalski <jaak@jkowalski.net>
翻譯:Dflying Chen:http://dflying.cnblogs.com/
原文:http://www.nlog-project.org/tutorial.html
本文為《NLog文章系列》的第二篇,將用實(shí)例程序演示用NLog書寫日志的方法。
應(yīng)用程序跟蹤介紹
很久以前,在那個(gè)沒有調(diào)試器,軟件也大都是基于控制臺(tái)的年代里,開發(fā)者習(xí)慣于使用printf()語句輸出跟蹤調(diào)試信息。而現(xiàn)在,世界發(fā)生了翻天覆地般的變化——printf()被Console.WriteLine()代替了……
我們都曾經(jīng)書寫過類似如下的代碼:
static void Main()
{
Console.WriteLine("SuperApp started.");
DoSomething();
Console.WriteLine("SuperApp finished.");
}
上面這段代碼中的Console.WriteLine() 就是所謂的“跟蹤”語句,因?yàn)檫@個(gè)語句除了輸出當(dāng)前程序的執(zhí)行狀態(tài)之外,并沒有什么其他用處。由Console.WriteLine() 的輸出也叫做應(yīng)用程序跟蹤。在上面的例子中,這兩條跟蹤語句就用來告訴我們DoSomething()方法是否執(zhí)行完畢。
在開發(fā)以及測(cè)試完成之后,我們可能會(huì)想要?jiǎng)h除這些跟蹤代碼,以提高序執(zhí)行效率(因?yàn)楦櫿{(diào)試語句執(zhí)行效率很低)。通常我們將這些跟蹤語句注釋掉,以便今后需要的時(shí)候可以方便地再次啟用。可是不幸的是,將跟蹤語句注釋掉之后,我們還需要重新編譯一遍程序。
或許有一天,在經(jīng)歷過第N次將無數(shù)的調(diào)試語句注釋和取消注釋之后,你會(huì)依稀感覺到這樣并不是一個(gè)好的解決方案,并期待著這樣的功能:
- 能夠通過簡(jiǎn)單的方法控制顯示哪些等級(jí)的跟蹤信息(例如只顯示警告和錯(cuò)誤級(jí)別的跟蹤信息,或是顯示所有級(jí)別的跟蹤信息等)。
- 將控制跟蹤信息的顯示與否的邏輯與應(yīng)用程序的視線代碼分開,跟蹤信息的顯示與否并不需要重新編譯應(yīng)用程序。
- 將跟蹤信息寫至文件、系統(tǒng)日志、消息隊(duì)列……
- 能夠?qū)⒁恍O為重要的信息通過Email發(fā)送給指定收信人,或是存放在數(shù)據(jù)庫(kù)中。
- 更多你能想到的……
有些朋友可能覺得,在圖形化調(diào)試器大行其道的當(dāng)今軟件開發(fā)環(huán)境中,這種書寫日志的跟蹤調(diào)試方式似乎用處非常有限。不過,當(dāng)你的程序每一秒都被成千上萬人同時(shí)訪問,哪怕是停機(jī)一分鐘都不能接受的時(shí)候,你就會(huì)知道這些調(diào)試信息對(duì)定位Bug來說意味著什么了(即所謂的“Live Site Debugging”)。
NLog是什么?
NLog((http://www.nlog-project.org)是一個(gè)基于.NET平臺(tái)編寫的類庫(kù),我們可以使用NLog在應(yīng)用程序中添加極為完善的跟蹤調(diào)試代碼。NLog完全實(shí)現(xiàn)了我們上面的期望目標(biāo),并且還遠(yuǎn)遠(yuǎn)不止這些……
NLog允許我們自定義從跟蹤消息的來源(source)到記錄跟蹤信息的目標(biāo)(target)的規(guī)則(rules)。記錄跟蹤信息的目標(biāo)(target)可以為如下幾種形式:
- 文件
- 文本控制臺(tái)
- 數(shù)據(jù)庫(kù)
- 網(wǎng)絡(luò)中的其它計(jì)算機(jī)(通過TCP或UDP)
- 基于MSMQ的消息隊(duì)列
- Windows系統(tǒng)日志
- 其他形式,請(qǐng)參考http://www.nlog-project.org/targets.html
除此之外,每一條跟蹤消息都可以自動(dòng)帶有上下文信息(contextual information),并將其發(fā)送給記錄跟蹤信息的目標(biāo)。這些上下文信息可以包含如下內(nèi)容:
- 當(dāng)前的日期和時(shí)間(多種格式)
- 記錄等級(jí)
- 來源名稱
- 輸出跟蹤消息的方法的堆棧信息
- 環(huán)境變量的值
- 異常的詳細(xì)信息
- 計(jì)算機(jī)、進(jìn)程和線程名稱
- 其他,請(qǐng)參考:http://www.nlog-project.org/layoutrenderers.html
每條跟蹤信息都包含一個(gè)記錄等級(jí)(log level)信息,用來描述該條信息的重要性。NLog支持如下幾種記錄等級(jí):
- Trace - 最常見的記錄信息,一般用于普通輸出
- Debug - 同樣是記錄信息,不過出現(xiàn)的頻率要比Trace少一些,一般用來調(diào)試程序
- Info - 信息類型的消息
- Warn - 警告信息,一般用于比較重要的場(chǎng)合
- Error - 錯(cuò)誤信息
- Fatal - 致命異常信息。一般來講,發(fā)生致命異常之后程序?qū)o法繼續(xù)執(zhí)行。
NLog是一個(gè)免費(fèi)的、基于BSD license發(fā)布的開源類庫(kù)。即使將其應(yīng)用于商業(yè)使用中,也基本上不會(huì)有任何的限制。NLog的二進(jìn)制可執(zhí)行文件以及原文件均可在http://www.nlog-project.org/download.html頁面中下載。我們同時(shí)還為NLog提供了圖形界面的安裝程序,您可以選擇NLog的安裝路徑,并可在安裝過程中添加如下內(nèi)容到Visual Studio集成開發(fā)環(huán)境中(同樣支持Express版本):
- 配置文件模板
- NLog配置文件智能感知支持
- 代碼片斷(code snippet)
- 集成至“Add Reference...”對(duì)話框
我們的第一個(gè)NLog應(yīng)用程序
接下來讓我們用Visual Studio 2005創(chuàng)建第一個(gè)使用NLog的應(yīng)用程序。該示例程序?qū)陌讶罩据敵龅娇刂婆_(tái)開始,并不斷添加新的功能,以演示在NLog中對(duì)日志進(jìn)行配置的方法。
首先在Visual Studio 2005中創(chuàng)建一個(gè)新項(xiàng)目(本示例程序?qū)⑹褂肅#演示),然后在“Add New Item...”對(duì)話框中為該程序添加一個(gè)NLog配置文件。這里我們選擇“Empty NLog Configuration File”,并命名為“NLog.config"”:
注意到NLog.dll的引用被自動(dòng)添加到了我們的項(xiàng)目中。剛剛添加的NLog.config文件的內(nèi)容如下,這也正是我們?cè)诒臼纠绦蛑袑⒁渲玫模?
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
</targets>
<rules>
</rules>
</nlog>
接下來需要一個(gè)額外的步驟:設(shè)置該配置文件的“Copy To Output Directory”選項(xiàng)為“Copy always”。這樣該配置文件將自動(dòng)被部署到*.exe所在的目錄下。這樣以后,無需任何設(shè)置,NLog即可自動(dòng)搜尋到并加載該配置文件。
接下來讓我們配置一下日志的輸出,在<targets />節(jié)中,添加一個(gè)新條目讓日志輸出到控制臺(tái)中,并添加必要的輸出布局(layout):
<targets>
<target name="console" xsi:type="Console"
layout="${longdate}|${level}|${message}"/>
</targets>
在輸入上述代碼時(shí),可以看到Visual Studio的智能感知功能發(fā)揮了作用:輸入xsi:之后,將得到當(dāng)前可用的輸出目標(biāo)列表:
然后,我們要在<rules />節(jié)中添加必要的規(guī)則,將所有記錄等級(jí)等于或高于Debug的信息輸出至控制臺(tái)。這段XML配置文件字解釋能力足夠強(qiáng),無需多言:
<rules>
<logger name="*" minlevel="Debug" writeTo="console"/>
</rules>
若希望生成并輸出診斷信息,我們還需要添加一個(gè)Logger對(duì)象。Logger對(duì)象的方法名和記錄等級(jí)的名稱一樣(Debug()、Info()、Fatal()……)。Logger對(duì)象是通過LogManager對(duì)象創(chuàng)建的。建議Logger對(duì)象的名稱和程序的類名保持一致。調(diào)用LogManager的GetCurrentClassLogger()方法即可自動(dòng)為當(dāng)前類創(chuàng)建一個(gè)Logger對(duì)象。
接下來開始修改Visual Studio自動(dòng)生成的這個(gè)C#文件。首先在文件頭部添加“using NLog”語句,引入NLog程序集的命名空間。然后添加創(chuàng)建Logger對(duì)象的代碼,注意在這里我們可以使用隨NLog的安裝而添加的Visual Studio的代碼片斷:輸入“nlogger”,然后按兩次Tab鍵即可。
using System;
using System.Collections.Generic;
using System.Text;
using NLog;
namespace NLogExample
{
class Program
{
private static Logger logger = LogManager.GetCurrentClassLogger();
static void Main(string[] args)
{
logger.Debug("Hello World!");
}
}
}
運(yùn)行該程序,將看到一條日志信息輸出到了控制臺(tái),該信息包含當(dāng)前的時(shí)間,記錄等級(jí),以及“Hello World”消息。
最后,讓我們總結(jié)一下實(shí)現(xiàn)該功能的步驟:
- 用LogManager.GetCurrentClassLogger(); 創(chuàng)建了一個(gè)Logger對(duì)象。該Logger對(duì)象代表與當(dāng)前類相關(guān)聯(lián)的日志消息的來源。
- 通過調(diào)用Logger對(duì)象的Debug()方法,發(fā)出一條Debug記錄等級(jí)的診斷信息。
- 因?yàn)橛涗浀燃?jí)和消息來源符合配置文件中的<rules />聲明,所以該消息將以指定的布局(layout)格式化后輸出到控制臺(tái)中。
稍微復(fù)雜一些的場(chǎng)景
接下來讓我們將這些日志信息,包括其中的一些上下文信息(例如堆棧信息等),輸出到文件和命令行兩個(gè)地方。要實(shí)現(xiàn)這個(gè)需求,我們只要修改NLog的配置文件,并添加一個(gè)類型為“File”的目標(biāo)即可。
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="console" xsi:type="ColoredConsole"
layout="${date:format=HH\:mm\:ss}|${level}|${stacktrace}|${message}"/>
<target name="file" xsi:type="File" fileName="${basedir}/file.txt"
layout="${stacktrace} ${message}"/>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="console,file"/>
</rules>
</nlog>
接下來這段C#代碼生成了更多的日志信息,還使用了NLog提供的一些其他方法用來輸出堆棧信息。
static void C()
{
logger.Info("Info CCC");
}
static void B()
{
logger.Trace("Trace BBB");
logger.Debug("Debug BBB");
logger.Info("Info BBB");
C();
logger.Warn("Warn BBB");
logger.Error("Error BBB");
logger.Fatal("Fatal BBB");
}
static void A()
{
logger.Trace("Trace AAA");
logger.Debug("Debug AAA");
logger.Info("Info AAA");
B();
logger.Warn("Warn AAA");
logger.Error("Error AAA");
logger.Fatal("Fatal AAA");
}
static void Main(string[] args)
{
logger.Trace("This is a Trace message");
logger.Debug("This is a Debug message");
logger.Info("This is an Info message");
A();
logger.Warn("This is a Warn message");
logger.Error("This is an Error message");
logger.Fatal("This is a Fatal error message");
}
運(yùn)行該程序,如下日志信息將被寫入應(yīng)用程序所在目錄中的“file.txt”文件中。
Program.Main This is a Trace message
Program.Main This is a Debug message
Program.Main This is an Info message
Program.Main => Program.A Trace AAA
Program.Main => Program.A Debug AAA
Program.Main => Program.A Info AAA
Program.Main => Program.A => Program.B Trace BBB
Program.Main => Program.A => Program.B Debug BBB
Program.Main => Program.A => Program.B Info BBB
Program.A => Program.B => Program.C Info CCC
Program.Main => Program.A => Program.B Warn BBB
Program.Main => Program.A => Program.B Error BBB
Program.Main => Program.A => Program.B Fatal BBB
Program.Main => Program.A Warn AAA
Program.Main => Program.A Error AAA
Program.Main => Program.A Fatal AAA
Program.Main This is a Warn message
Program.Main This is an Error message
Program.Main This is a Fatal error message
同時(shí),控制臺(tái)中也輸出了如下漂亮的日志信息。
再來修改一下配置文件——開發(fā)中一個(gè)很常見的需求就是讓不同記錄等級(jí)的日志輸出到不同的目標(biāo)中。例如,讓記錄等級(jí)等于或高于Info的信息輸出至控制臺(tái),同時(shí)將任意記錄等級(jí)的信息都存放在文件中保存。在NLog中,實(shí)現(xiàn)這個(gè)需求只要修改配置文件的<rules />節(jié)即可,無需修改應(yīng)用程序。
<rules>
<logger name="*" minlevel="Info" writeTo="console"/>
<logger name="*" minlevel="Trace" writeTo="file"/>
</rules>
再次運(yùn)行程序,可以看到Trace和Debug等級(jí)的信息只出現(xiàn)在了文件中,而并不顯示在控制臺(tái)中。
(待續(xù)……)
浙公網(wǎng)安備 33010602011771號(hào)