之前我介紹過如何使用log4net來記錄日志,但最近喜歡上了另一個簡單好用的日志架構NLog。 關于NLog和log4net的比較這裡就不多讨論了,感興趣的朋友可以參看.NET日志工具介紹和log4net vs. Nlog這兩篇文章。本文主要介紹一下如何在項目中使用NLog。
在Nuget中安裝NLog
NLog可以直接使用Nuget安裝: PM > Install-Package Nlog
使用NLog
NLog的使用方式基本上和其它的Log庫差不多,分為Trace、Debug、Info、Error、Fatal五個等級
private static Logger logger = LogManager.GetCurrentClassLogger();
static void Main(string[] args)
{
logger.Trace("Trace Message");
logger.Debug("Debug Message");
logger.Info("Info Message");
logger.Error("Error Message");
logger.Fatal("Fatal Message");
}
不過它提供的方法倒是蠻多的,光Trace就有42種重載形式。雖然功能強大事件好事,但某種程度上也增加了學習成本。
配置NLog
執行了上面的語句後,實際上是沒有任何效果的。因為我們還沒有配置日志的輸出路徑。這個輸出路徑一般是在配置檔案中配置的(也支援寫死),NLog支援兩種配置檔案格式
- 配置資訊嵌入在.NET應用程式标準的*.exe.config或者web.config檔案裡
- 儲存在獨立檔案裡,也叫單一格式
第一張方式比較正常,但我不喜歡這種方式,因為它和其它與日志無關的配置寫在一塊兒了,不友善在不同的項目中共享配置。這裡主要介紹下獨立檔案的方式。NLog支援如下三種檔案名的配置檔案:"NLog.config"、"*.exe.nlog"和"NLog.dll.nlog",我比較喜歡第一種。不管哪一種,其内容是一樣的,一個簡單的示例如下:
<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="Console" />
<target name="debugger"
xsi:type="Debugger"
layout="${date:format=HH\:mm\:ss.fff}: ${message}" />
<target name="error_file"
xsi:type="File"
fileName="${basedir}/Logs/Error/${shortdate}/error.txt" maxArchiveFiles="30"
layout="${longdate} | ${level:uppercase=false} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}" />
</targets>
<rules>
<!--<logger name="*" writeTo="console" />-->
<logger name="*"
minlevel="Debug"
writeTo="debugger" />
<logger name="*"
minlevel="Error"
writeTo="error_file" />
</rules>
</nlog>
它主要包括兩個部分:輸出目标target和路由規則rule。下面就分别介紹一下他們。
輸出目标target
每個target代表一個輸出目标,它主要包含兩個屬性:name和type。name是輸出模闆的名稱,在後面的路由規則中使用,type則是輸出類型,常見的有
- Console 輸出到控制台
- Debugger 輸出到
- File 輸出到檔案
- Mail 輸出為郵件發送
- Network 輸出到網絡位址
- Database 輸出到資料庫
當選擇某一種類型的時候,還需要配置相應的參數。如輸出類型是File時,我們要配置日志路徑filename,這裡是可以使用一些變量的(花括号裡面的部分),我這裡的例子:
fileName="${basedir}/Logs/Error/${shortdate}/error.txt"
輸出的日志格式為 /Log/2014-10-01/err.txt 每天生成一個檔案夾,非常友善。
輸出格式的控制:
有的時候,我們需要對時間、異常等這些對象的輸出格式進行控制。它們可以通過修改layout參數來實作。這一部分是相對比較複雜的,不在本文讨論範圍之列,有空的話我再專門介紹下。
參考示例:
網上有許多現成的示例,直接參考一下比從頭寫起要們節省不少時間,這裡我簡單的列舉兩個,歡迎讀者朋友推薦。
順便這兒也貼一個我常用的配置文檔:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--螢幕列印消息-->
<target name="console"
xsi:type="ColoredConsole"
layout="${date:format=HH\:mm\:ss}> ${message}"/>
<!--VS輸出視窗-->
<target name="debugger"
xsi:type="Debugger"
layout="${date:format=HH\:mm\:ss} | ${level:padding=-5} | ${message}" />
<!--儲存至檔案-->
<target name="error_file"
xsi:type="File"
maxArchiveFiles="30"
fileName="${basedir}/Logs/Error/${shortdate}/error.txt"
layout="${longdate} | ${level:uppercase=false:padding=-5} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}" />
<logger name="*"
minlevel="Debug"
writeTo="debugger" />
<logger name="*"
minlevel="Error"
writeTo="error_file" />
</nlog>
路由規則rule
路由規則主要用于将日志和輸出目标比對起來,它一般有如下幾個屬性
- name - 記錄者的名字 (允許使用通配符*)
- minlevel - 比對日志範圍的最低級别
- maxlevel - 比對日志範圍的最進階别
- level - 比對的單一日志級别
- levels - 比對的一系列日志級别,由逗号分隔。
- writeTo - 規則比對時日志應該被寫入的一系列目标,由逗号分隔。
看上去有好幾個屬性,實際上用起來還是比較簡單的,例如我前面的三條規則解釋如下:
<logger name="*"
writeTo="console" /> 将所有的日志輸出到控制台中
minlevel="Debug"
writeTo="debugger" /> 将Debug級别以上的日志輸出到Debugger中
minlevel="Error"
writeTo="error_file" /> 将Error級别以上的日志輸出到檔案中
另外,NLOG支援配置多個路由規則,可以非常友善我們的輸出。
由于篇幅有限,這裡介紹得比較簡略。更詳細的配置檔案設定可以參看官方文檔
簡單的封裝:
前面已經列舉過NLog的使用方法,雖然其使用并不算發雜,但一個簡單的Wrapper可以降低使用門檻,規範使用方式,甚至友善後期切換日志架構,很多時候還是非常有必要的。這裡給一個簡單的封裝:
1 class Logger
2 {
3 NLog.Logger logger;
4
5 private Logger(NLog.Logger logger)
6 {
7 this.logger = logger;
8 }
9
10 public Logger(string name)
11 :this(NLog.LogManager.GetLogger(name))
12 {
13 }
14
15 public static Logger Default { get; private set; }
16 static Logger()
17 {
18 Default = new Logger(NLog.LogManager.GetCurrentClassLogger());
19 }
20
21 public void Debug(string msg, params object[] args)
22 {
23 logger.Debug(msg, args);
24 }
25
26 public void Debug(string msg, Exception err)
27 {
28 logger.Debug(msg, err);
29 }
30
31 public void Info(string msg, params object[] args)
32 {
33 logger.Info(msg, args);
34 }
35
36 public void Info(string msg, Exception err)
37 {
38 logger.Info(msg, err);
39 }
40
41 public void Trace(string msg, params object[] args)
42 {
43 logger.Trace(msg, args);
44 }
45
46 public void Trace(string msg, Exception err)
47 {
48 logger.Trace(msg, err);
49 }
50
51 public void Error(string msg, params object[] args)
52 {
53 logger.Error(msg, args);
54 }
55
56 public void Error(string msg, Exception err)
57 {
58 logger.Error(msg, err);
59 }
60
61 public void Fatal(string msg, params object[] args)
62 {
63 logger.Fatal(msg, args);
64 }
65
66 public void Fatal(string msg, Exception err)
67 {
68 logger.Fatal(msg, err);
69 }
70 }
View Code
雖然比較簡單,但大多數簡單的場景下還是夠用的。如果要更強大一點的封裝可以考慮 Common.Logging, SimpleLoggingFacade等一些成型的庫。
第三方檢視工具
和log4net一樣,NLog也是被一些第三方log檢視工具所支援的,我這裡就搜尋到了兩個:Sentinel和 Harvester 。我用這些檢視工具的地方不大多,沒有具體去研究它們。不過NLog是支援DB輸出的,感覺輸出到DB中後用SQL查詢要更加友善而強大些,就是實時性差些。
學習資料:
本文這裡隻是友善NLOG快速入門,仍屬于管中窺豹階段,NLOG本身還是非常強大的,園子裡有一系列文章進行了比較深入的介紹
1 class Logger
2 {
3 NLog.Logger logger;
4
5 private Logger(NLog.Logger logger)
6 {
7 this.logger = logger;
8 }
9
10 public Logger(string name)
11 :this(NLog.LogManager.GetLogger(name))
12 {
13 }
14
15 public static Logger Default { get; private set; }
16 static Logger()
17 {
18 Default = new Logger(NLog.LogManager.GetCurrentClassLogger());
19 }
20
21 public void Debug(string msg, params object[] args)
22 {
23 logger.Debug(msg, args);
24 }
25
26 public void Debug(string msg, Exception err)
27 {
28 logger.Debug(msg, err);
29 }
30
31 public void Info(string msg, params object[] args)
32 {
33 logger.Info(msg, args);
34 }
35
36 public void Info(string msg, Exception err)
37 {
38 logger.Info(msg, err);
39 }
40
41 public void Trace(string msg, params object[] args)
42 {
43 logger.Trace(msg, args);
44 }
45
46 public void Trace(string msg, Exception err)
47 {
48 logger.Trace(msg, err);
49 }
50
51 public void Error(string msg, params object[] args)
52 {
53 logger.Error(msg, args);
54 }
55
56 public void Error(string msg, Exception err)
57 {
58 logger.Error(msg, err);
59 }
60
61 public void Fatal(string msg, params object[] args)
62 {
63 logger.Fatal(msg, args);
64 }
65
66 public void Fatal(string msg, Exception err)
67 {
68 logger.Fatal(msg, err);
69 }
70 }