原文連接:https://github.com/NLog/NLog/...
NOTE: 本文章由 赤石俊哉 翻譯整理,您能夠以學習交流爲目的進行任意使用。如需商用請徵得原做者以及譯者的贊成。git
NLog能夠從Nuget上下載。
你只須要安裝NLog.Config包,它將會同時安裝NLog和NLog.Schema包。
最後將會爲工程添加一個初級的設置和智能補全(Intellisense)。
使用GUI或者在程序包管理命令行中輸入:github
Install-Package NLog.Config
你如今就能夠編譯你的程序而後開始使用NLog了。安全
NOTE【譯者注】
Log就是常說的日誌信息。app
爲了從你的程序中建立你所須要的日誌消息你須要使用日誌記錄API。Logger
和LogManager
這兩個類將會很常常的被使用到,它們都在NLog命名空間裏面。Logger
表明了一些被命名的日誌源,並且他們有能夠發出日誌消息的成員方法。LogManager
則是用於建立和管理Logger
對象的實例。異步
有一點你必需要理解的很重要的是,Logger
並不表明任何特定的日誌輸出(所以,它並不與任何特定的日誌文件等相關聯),它只是一個源,它一般對應你代碼中的一個類。
從日誌源到輸出型式的映射經過配置文件和配置API分開定義。
保持這樣的分離是爲了讓你能夠在代碼中繼續寫日誌聲明,經過更新一處的設置能夠簡單地變換日誌的輸出型式和輸出位置。async
建議爲每個類單首創建一個(private static
)Logger
對象。就如咱們以前所說的,你須要使用LogManager
去建立Logger
的實例。
下面的代碼將會建立一個和class
有着相同名字的Logger
。函數
namespace MyNamespace { public class MyClass { private static Logger logger = LogManager.GetCurrentClassLogger(); } }
管理Logger
的名字也是能夠的:性能
using NLog; Logger logger = LogManager.GetLogger("MyClassName");
由於Logger對象是線程安全的,因此你能夠簡單地建立它並存放在一個static
變量中。學習
每個日誌消息都用一個日誌級別來修飾,它們用來識別消息的重要性和具體細節。NLog能夠以Logger對象的名稱和日誌級別爲主,路由日誌消息。測試
NLog支持下面的日誌級別:
Trace
- 特別細節的日誌,可能包含大量的信息,好比說協議的負載。這個日誌級別一般只會在開發期間被啓用。
Debug
- Debug信息,比Trace
的信息量要少一些,一般不會在生產環境下使用。
Info
- 信息消息,這個是在生產環境下常用到的。
Warn
- 警告消息,一般用來指示非關鍵性的問題,這些問題能夠被恢復或者只是臨時錯誤。
Error
- 錯誤消息 - 大多數時候,他們都是Exception
(異常)。
Fatal
- 特別嚴重的錯誤!
你能夠簡單地經過調用Logger
對象的其中一個成員方法來書寫日誌消息。Logger
類有六個成員函數,和它們的日誌級別相符合:Trace()
,Debug()
,Info()
,Warn()
,Error()
,Fatal()
。
固然,也有一個成員函數叫Log()
,你能夠將日誌級別做爲參數來調用這個方法。
using NLog; public class MyClass { private static Logger logger = LogManager.GetCurrentClassLogger(); public void MyMethod1() { logger.Trace("Sample trace message"); logger.Debug("Sample debug message"); logger.Info("Sample informational message"); logger.Warn("Sample warning message"); logger.Error("Sample error message"); logger.Fatal("Sample fatal error message"); // alternatively you can call the Log() method // and pass log level as the parameter. logger.Log(LogLevel.Info, "Sample informational message"); } }
日誌消息也能夠被參數化 - 你可使用字符串格式,就像你在Console.WriteLine()
和String.Format()
中同樣:
using NLog; public class MyClass { private static Logger logger = LogManager.GetCurrentClassLogger(); public void MyMethod1() { int k = 42; int l = 100; logger.Trace("Sample trace message, k={0}, l={1}", k, l); logger.Debug("Sample debug message, k={0}, l={1}", k, l); logger.Info("Sample informational message, k={0}, l={1}", k, l); logger.Warn("Sample warning message, k={0}, l={1}", k, l); logger.Error("Sample error message, k={0}, l={1}", k, l); logger.Fatal("Sample fatal error message, k={0}, l={1}", k, l); logger.Log(LogLevel.Info, "Sample informational message, k={0}, l={1}", k, l); } }
TIP: 你應當儘可能避免本身進行字符串格式化來替代使用NLog中內建的格式化方法(好比:鏈接,以及自行調用
String.Format()
)。具體緣由表如今:
格式化日誌消息須要花費很長時間,因此NLog嘗試將格式化操做推遲到了當日志消息須要被輸出的時候。若是消息的最後處理被跳過了,因爲日誌記錄配置,你將不須要花費時間在String.Format()
上。具體參見日誌記錄性能最優化。
雖然到如今爲止咱們已經學習瞭如何從代碼中建立日誌消息,可是咱們尚未對咱們的日誌進行任何的配置輸出。因此,當你運行你的測試應用程序時,你將會看到……好吧,啥都沒有。如今咱們打開NLog.config
文件而後添加一些日誌規則:
在<targets>
部分中,添加:
<target name="logfile" xsi:type="File" fileName="file.txt" />
這將會定義一個目標,日誌將會被輸出到一個叫作file.txt
的文件中。
在<rules>
部分中,添加:
<logger name="*" minlevel="Info" writeTo="logfile" />
這個片斷將會引導Info
級別以及更高級別(包括Info
,Warn
,Error
和Fatal
)的全部日誌(name="*"
)輸出到一個已命名爲logfile
的目標。
注意,當你將這個在Visual Studio中輸入時,你應該能夠看到IntelliSense會建議屬性名而且驗證他們的值。最後的配置文件應該像這樣:
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target name="logfile" xsi:type="File" fileName="file.txt" /> </targets> <rules> <logger name="*" minlevel="Info" writeTo="logfile" /> </rules> </nlog>
讓咱們來試試更復雜的東西吧。想象一下你想要將很是細節的日誌發送到一個文件,並且你也但願在控制檯窗口中看到他們,可是在控制檯窗口中細節稍微少一些。下面的配置文件能夠實現這樣的需求:
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target name="logfile" xsi:type="File" fileName="file.txt" /> <target name="console" xsi:type="Console" /> </targets> <rules> <logger name="*" minlevel="Trace" writeTo="logfile" /> <logger name="*" minlevel="Info" writeTo="console" /> </rules> </nlog>
如你所見,咱們如今有多個目標,並且有多個規則來路由日誌到目標。
還有一個比較常見的應用場景則是,須要爲當前正在開發的組件提供更多細節的日誌,而其餘的組件將會減小輸出。咱們就能夠用這樣的配置文件:
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target name="logfile" xsi:type="File" fileName="file.txt" /> </targets> <rules> <logger name="SomeNamespace.Component.*" minlevel="Trace" writeTo="logfile" final="true" /> <logger name="*" minlevel="Info" writeTo="logfile" /> </rules> </nlog>
第一個規則將會將以SomeNamespace.Component
開頭的Logger對象的Trace
級別及以上級別的日誌發送到日誌文件。屬性final=true
將會使得在寫入操做以後中止進一步處理。
第二個規則將會將剩下的日誌發送到同一個日誌文件,可是這些日誌有一個約束,那就是級別須要是Info
或更高。
NLog支持特殊類型的目標,從而不須要它們本身作任何日誌記錄,而是修改其餘Logger的行爲。這些特殊的目標就稱之爲封裝器。最經常使用的封裝器有:
ImpersonatingWrapper - 在寫入期間冒充另外一個用戶。
AsyncWrapper - 提供異步操做,目標的寫入的緩衝執行。
FallbackGroup - 提供錯誤時回滾。
FilteringWrapper - 用一些條件爲基礎從總體日誌中進行篩選。
還有不少其餘的封裝器可使用,具體列表你能夠看這裏。
爲了使用封裝器,簡單地使用一對括起來的<target />
元素用來表示封裝器,而後在<rules/>
部分中使用封裝器的名字,下面是一個例子:
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target name="asyncFile" xsi:type="AsyncWrapper"> <target name="logfile" xsi:type="File" fileName="file.txt" /> </target> </targets> <rules> <logger name="*" minlevel="Info" writeTo="asyncFile" /> </rules> </nlog>
這樣文件的所有寫入操做都是異步的了,將會提升調用線程的響應速度。
層級提供了一個當日志被寫入文件時,指定日誌內容格式的方法。主要有兩種層級:
簡單層級 - 使用層級渲染器撰寫。
結構層級 - 能夠輸出XML、CSV、以及其餘複雜的格式。
簡單層級就是一個字符串,在${
和}
中嵌入一些特殊的標記。好比下面的聲明將會使得每一條日誌消息都是用一個格式爲yyyMMddHHmmss:
的日期前綴:
<target name="logfile" xsi:type="File" fileName="file.txt" layout="${date:format=yyyyMMddHHmmss} ${message}" />
當咱們但願將Logger對象展開到子對象的時候,咱們可使用下面的代碼:
class BaseClass { protected BaseClass() { Log = LogManager.GetLogger(GetType().FullName); } protected Logger Log { get; private set; } } class ExactClass : BaseClass { public ExactClass() : base() { } ... }
在父類(BaseClass)的構造函數中,LogManger.GetLogger()
方法不該該使用Type
參數自變量,也就是:
protected BaseClass() { Log = LogManager.GetLogger(GetType().FullName, GetType()); }
這樣調用會引起一個異常。
萬一ExactClass
有一個默認的調用了BaseClass
構造函數的構造函數,那麼,System.StackOverflowException
就會被引起。這是由於在異常被引起以前,ExactClass
嘗試着調用了BaseClass
的GetLogger(String, Type)
來構造ExactClass
。
ExactClass => BaseClass => ExactClass => BaseClass => ...
當ExactClass
不存在默認的構造函數時,GetLogger(String, Type)
方法調用不知道如何去構造ExactClass
,則引起NLog.NLogConfigurationException
。