.NET Core - 使用 NLog 紀錄日誌資訊

前言

在所有程式系統中,Log紀錄是不可或缺的部份,我們可以查看產生的錯誤訊息,快速的找出問題點。.NET中有許多好用的Log工具(如NLog、Log4net等等)提供簡單好使用的方式讓我們輕鬆地可以將需要的資訊生成相關日誌內容,另外.NET Core 提供了標準化的 Log (Microsoft.Extensions.Logging),支援多種 Log 輸出,而Nlog就是其中之一

因為第一次在專案內使用,在這邊簡單的紀錄該套件的基本使用,方便自己之後建立新專案時參考,若有問題或任何建議歡迎提出一起討論

Nlog介紹

套件Github首頁:https://github.com/NLog/NLog
Github Wiki:https://github.com/nlog/nlog/wiki

功能:

  • 可以在程式裡去處理已知異常(捕捉try…catch),並依據異常狀況給予不同等級
  • 可以依據使用者定義的等級做後續不同處理方式的操作

Log儲存方式:

常見的做法是儲存到文字檔、資料庫或是寄送E-mail通知
還有一些比較新潮的做法是搭配用SignalR推播、直接把log丟到Slack等等
現在讓我們來進行實作一下

新增.NET Core API 專案

這邊使用.NET Core API 專案來方便展示

安裝 Nlog

透過 NuGet 安裝 Nlog 到專案中

新增 Nlog.config

放在Asp .net core專案的root 資料夾上
新增方式有兩種:
1.自己手動新增檔案
2.安裝套件NLog.config自動產生檔案
這裡可依照喜好自行選擇,這裡採用官網Wiki的方式手動建立,以下使用官網的範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?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"
autoReload="true"
internalLogLevel="Info"
internalLogFile="c:\temp\internal-nlog.txt">

<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>

<!-- the targets to write to -->
<targets>
<!-- write logs to file -->
<target xsi:type="File" name="allfile" fileName="c:\temp\nlog-all-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />

<!-- another file log, only own logs. Uses some ASP.NET core renderers -->
<target xsi:type="File" name="ownFile-web" fileName="c:\temp\nlog-own-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
</targets>

<!-- rules to map from logger name to target -->
<rules>
<!--All logs, including from Microsoft-->
<logger name="*" minlevel="Trace" writeTo="allfile" />

<!--Skip non-critical Microsoft logs and so log only own logs-->
<logger name="Microsoft.*" maxlevel="Info" final="true" /> <!-- BlackHole without writeTo -->
<logger name="*" minlevel="Trace" writeTo="ownFile-web" />
</rules>
</nlog>

這邊來講解一下該設定檔,內容常設定的有 <targets><rules> 兩大塊,分別可設定輸出規則及log寫入規則,兩者必須要搭配使用:

  • targets 用來定義寫入log 格式、儲存的檔案位置與檔名
  • rules裡面可以自訂Log寫入規則,例如指定logger名稱、最小LogLevel等,最重要的是要指定輸出的target(writeTo)

    一條rule至少要指定一個對應的target,但也可以輸出給多個target,而一個target也可以對應多個rule

另外NLog 根節點上也有一些功能可以設定開關,這邊提及幾個較常用的

1
2
3
4
5
6
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
throwExceptions="true"
internalLogLevel="Info"
internalLogFile="c:\temp\internal-nlog.txt">
  • autoReload:在NLog.config修改時自動載入
  • throwExceptions:Nlog預設會忽略所有發生的錯誤(Ex:無法寫入Log),當需要偵錯時可以設定為 true,開啟後便可以知道為什麼沒成功寫入Log。

如果NLog無法正常寫入時,則可能需要啟用內部日誌記錄。

  • internalLogLevel="Off|Trace|Debug|Info|Warn|Error|Fatal":設定內部日誌級別。級別越高,內部日誌輸出越詳細。
  • internalLogFile:設定內部日誌紀錄檔案寫入的位置。

設定 nlog.config 輸出至目錄 方式

設定 config 檔案的屬性 複製至輸出目錄 為 有更新時才複製永遠複製,已確保執行時能找到最新狀態的 nlog.config 檔案

更新 Program.cs

這邊參考官網的教學,加入命名空間,清掉預設的 Log Provider,並使用UseNLog()注入DI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Web;

namespace NlogExercise
{
public class Program
{
public static void Main(string[] args)
{
var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
{
logger.Debug("init main");
CreateHostBuilder(args).Build().Run();
}
catch (Exception exception)
{
//NLog: catch setup errors
logger.Error(exception, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
}
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseNLog(); // NLog: setup NLog for Dependency injection
}
}

調整 appsettings.json

調整 appsettings.json,否則 appsettings.json 會將 SetMinimumLevel 設定覆蓋掉

1
2
3
4
5
6
7
8
9
10
11
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Trace",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

這邊依需求情境為主,如果沒有做SetMinimumLevel設定則不用特別修改appsettings.json

寫入日誌紀錄

接著只要在需要的地方注入 ILogger來紀錄log,我們開啟預設的 WeatherForecastController ,確認在建構子有注入ILogger,然後就可以於Get方法中輸出Log記錄了

查看日誌

當我們執行該Web Api專案後,在我們輸出日誌的資料夾會產出三個檔案

internal-nlog.txt:

1
2
3
4
5
2020-12-10 14:35:02.5675 Info Message Template Auto Format enabled
2020-12-10 14:35:02.5858 Info Loading assembly: NLog.Web.AspNetCore
2020-12-10 14:35:02.6625 Info Adding target FileTarget(Name=allfile)
2020-12-10 14:35:02.6625 Info Adding target FileTarget(Name=ownFile-web)
2020-12-10 14:35:02.7270 Info Validating config: TargetNames=allfile, ownFile-web, ConfigItems=45, FilePath=C:\Users\SENB_014\source\repos\NlogExercise\NlogExercise\bin\Debug\netcoreapp3.1\nlog.config

nlog-all-2020-12-10.log

1
2
3
4
5
6
7
8
9
10
2020-12-10 14:35:02.7922||DEBUG|NlogExercise.Program|init main 
2020-12-10 14:35:04.5343||INFO|Microsoft.Hosting.Lifetime|Now listening on: https://localhost:5001
2020-12-10 14:35:04.5463||INFO|Microsoft.Hosting.Lifetime|Now listening on: http://localhost:5000
2020-12-10 14:35:04.5463||INFO|Microsoft.Hosting.Lifetime|Application started. Press Ctrl+C to shut down.
2020-12-10 14:35:04.5463||INFO|Microsoft.Hosting.Lifetime|Hosting environment: Development
2020-12-10 14:35:04.5463||INFO|Microsoft.Hosting.Lifetime|Content root path: C:\Users\SENB_014\source\repos\NlogExercise\NlogExercise
2020-12-10 14:35:05.7936||INFO|NlogExercise.Controllers.WeatherForecastController|--Information--
2020-12-10 14:35:05.7936||WARN|NlogExercise.Controllers.WeatherForecastController|Warning
2020-12-10 14:35:05.7936||ERROR|NlogExercise.Controllers.WeatherForecastController|--Error--
2020-12-10 14:35:05.7936||FATAL|NlogExercise.Controllers.WeatherForecastController|--Critical--

nlog-own-2020-12-10.log

1
2
3
4
5
2020-12-10 14:35:02.7922||DEBUG|NlogExercise.Program|init main |url: |action: 
2020-12-10 14:35:05.7936||INFO|NlogExercise.Controllers.WeatherForecastController|--Information-- |url: https://localhost/weatherforecast|action: Get
2020-12-10 14:35:05.7936||WARN|NlogExercise.Controllers.WeatherForecastController|Warning |url: https://localhost/weatherforecast|action: Get
2020-12-10 14:35:05.7936||ERROR|NlogExercise.Controllers.WeatherForecastController|--Error-- |url: https://localhost/weatherforecast|action: Get
2020-12-10 14:35:05.7936||FATAL|NlogExercise.Controllers.WeatherForecastController|--Critical-- |url: https://localhost/weatherforecast|action: Get

結語

這篇簡單分享 NLog 在 .NET Core 的使用方式並運用在專案中,設定上十分友善,至於許多客製化的設定可以參考官方的文件,之後有時間再和大家分享儲存log至其他地方的用法

參考資料

Getting-started-with-ASP.NET-Core-3