天天看點

一個簡單好用的日志架構NLog

之前我介紹過如何使用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支援兩種配置檔案格式

  1. 配置資訊嵌入在.NET應用程式标準的*.exe.config或者web.config檔案裡
  2. 儲存在獨立檔案裡,也叫單一格式

第一張方式比較正常,但我不喜歡這種方式,因為它和其它與日志無關的配置寫在一塊兒了,不友善在不同的項目中共享配置。這裡主要介紹下獨立檔案的方式。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可以降低使用門檻,規範使用方式,甚至友善後期切換日志架構,很多時候還是非常有必要的。這裡給一個簡單的封裝: 

一個簡單好用的日志架構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     }      

View Code

雖然比較簡單,但大多數簡單的場景下還是夠用的。如果要更強大一點的封裝可以考慮 Common.Logging, SimpleLoggingFacade等一些成型的庫。

第三方檢視工具

和log4net一樣,NLog也是被一些第三方log檢視工具所支援的,我這裡就搜尋到了兩個:Sentinel和 Harvester 。我用這些檢視工具的地方不大多,沒有具體去研究它們。不過NLog是支援DB輸出的,感覺輸出到DB中後用SQL查詢要更加友善而強大些,就是實時性差些。

學習資料:

本文這裡隻是友善NLOG快速入門,仍屬于管中窺豹階段,NLOG本身還是非常強大的,園子裡有一系列文章進行了比較深入的介紹

一個簡單好用的日志架構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     }