Dot Net Core Log 透過相依注入 NLog

相信大家對於 Log 的重要性都有一定的認知,本篇筆者分享一下如何透過注入 NLog 並且透過 Mircosoft.Extensions.Logging 來解除對於 NLog 的相依,藉此實作 Dot Net Core Log 機制。

大家在使用Logger紀錄Log時常會有個問題,要用NLog還是log4net,再來就是實體要怎麼生成,要用Singleton還是要用static函式,最後要怎麼統一Log的格式,今天筆者來分享我的作法:

  • 利用 Mircosoft.Extensions.Logging 來將Logger抽象化,從此不用在實做時擔心要用NLog或是log4net。
  • 利用相依注入,實作只需要在建構子說明需要什麼,不需要考慮需要元件的生成與消滅。
  • 學習 NLog 的設定檔設定方式以及自定義擴充方法來格式化Log的內容。

相依套件以及環境設定

此篇文章是基於.Net Core的版本寫成的,以下列出所需套件:

  • NLog.Config
  • NLog.Web.AspNetCore

由於安裝 NLog.Web.AspNetCore 就會安裝 Mircosoft.Extensions.Logging 所以不將其列在相依套件,接下來就一步一步說明。

實作方式

Mircosoft.Extensions.Logging

我們使用 Mircosoft.Extensions.Logging 是要將Logger 抽象化,也就是使用 Logger 的物件相依的是 Mircosoft.Extensions.Logging 的ILogger而不是 NLog 的。這樣做之後如果要更換 Logger 的實體就不會影響到程式碼本身了。
說了這麼多接下來就看看筆者怎麼實作,首先假設我們要實作一個 HomeController 我們只要透過建構子將 ILogger 注入即可,請看以下程式碼:

public class HomeController : Controller
{
    private readonly ILogger _logger;

    public LoggerService(ILogger<HomeController> logger)
    {
        _logger = logger;
    }

    public IActionResult Index () {
        _logger.LogInformation("This is Index Log");
        return View ();
    }
}

如此當使用者造訪 HOME\Index\ 時他就會使用注入的 logger 的 LogInformation 的方法了,此時也不用在乎其使用的是 NLog 還是 log4net 了,這就看注入的 Logger 是哪一個了。

注入

當使用 .Net Core 注入就變得容易許多了,這裡只需要在 Program.cs 加入一段程式碼即可。

using NLog.Web; // <--記得Using這個不然C#不認識要新增的方法.
        .
        .
        .
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .UseNLog(); // <--多加這行即可

由於引用 NLog.Web 會有擴充方法 UseNLog讓注入在一行內完成。

格式化 Log 內容

也許使用者會覺得 LogInformation 這方法名稱太長,想要改短一點,又或者想要紀錄方法名稱跟行號,這時我們來自定擴充方法,透過擴充方法來格式化 Log 的內容,以及使用自訂義的方法名稱,這裡我們加入 ILogger.Extension.cs 並加入以下內容:

using System.Runtime.CompilerServices;
namespace ILogger.Extension
{
    public static class ILoggerExtensions
    {
        public static void Info(this ILogger logger,
            string log,
            [CallerMemberName] string name = "",
            [CallerLineNumber] int line = 0)
        {
            logger.LogInformation($"Method:{name}, Line:{line}, Message:{log}");
        }
    }   
}

這裡我們使用 呼叫資訊 來列出方法名稱及行號,並定義每個 Log 都包含這資訊。
接下來在使用到 ILogger 的地方多 using 這個 namespace 就可以使用這個擴充方法了。

當然 Log 的層級不只是 Info 而已,接下來再請使用者依樣畫葫蘆實作其他層級吧。

NLog Config 設定

當安裝 NLog.Config 安裝程式會在執行檔所在目錄產生 NLog.config 檔案,接下來簡單修改就可以把 Log 寫到檔案內,以下範例真對設定內容做一簡單的說明:

<?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"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">

  <targets>

        <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
            layout="${longdate} ${uppercase:${level}} ${message}" />
  </targets>

  <rules>
    <!-- add your logging rules here -->

    <logger name="Microsoft.*" maxlevel="Info" final="true" /> <!-- BlackHole without writeTo -->
    <logger name="*" minlevel="Debug" writeTo="f" />
  </rules>
</nlog>

這邊做個簡單介紹,首先設定一下 target 再來設定 rules 把對應的 LOG 寫到 target 內,簡單講 target 是要寫到哪裡, rules 就是想要紀錄的 Log 條件。更進一步內容請見 NlogConfiguration

結語

今天跟大家分享一下筆者於 .Net Core 實作Logger 機制的方式,藉由這樣的架構可以任意抽換 Logger 的實作,而不會影響程式的實作,希望這篇文章能讓大家有所收穫。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *