.NET Logger 寫入資料庫 - NLog
NET Logger 寫入資料庫 - NLog
系統紀錄使用者操作、錯誤訊息或是活動日誌紀錄是很常見的需求,ASP.NET Core 預設上就使用了Logger Framework,並且透過這個Logger API 可以很輕鬆與第三方套件如 NLog、Log4Net 完美搭配,在紀錄上更方便了,這邊主要記錄幾個用過的套件,第一款是 NLog,NLog 也是我的首選,安裝說明文件相當清楚,基本上根據官方Getting started,一步步設定即可,這次趁著升級,順便把筆記重新翻寫一下。
環境
- .NET Core 3.1
- Nuget > NLog.Web.AspNetCore
- Nuget > Microsoft.Data.SqlClient
實作
-
安裝
NLog.Web.AspNetCore
官方文件有另外安裝 NLog,但我沒有安裝也可以正常執行,如果不是AspNetCore專案,建議還是安裝
-
安裝
Microsoft.Data.SqlClient
( 或System.Data.SqlClient
)NLog 寫入MSSQL是使用傳統的 ADO.NET 方式,所以要額外安裝
Microsoft.Data.SqlClient
安裝
Microsoft.Data.SqlClient
後要在nlog.config
中的target
指定dbProvider
,如果是安裝System.Data.SqlClient
似乎不指定也可以 -
新增
nlog.config
檔案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 46 47 48 49 50 51 52 53 54
<?xml version="1.0" encoding="utf-8" ?> <!-- 設定internalLogFile可以得知NLog的內部錯誤,在初始設定時很有幫助 --> <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> <!-- 儲存目標 --> <targets> <!-- 儲存目標類型為 "文字檔案" --> <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}" /> <!-- 儲存目標類型為 "資料庫" --> <target name="database" xsi:type="Database" dbProvider="Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient"> <connectionString>Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=LoggerTest;Integrated Security=True</connectionString> <commandText> INSERT INTO dbo.LogTest (Logged, Level, Message, Logger, Exception) VALUES (@Logged, @Level, @Message, @Logger, @Exception); </commandText> <parameter name="@Logged" layout="${date}" /> <parameter name="@Level" layout="${level}" /> <parameter name="@Message" layout="${message}" /> <parameter name="@Logger" layout="${logger}" /> <parameter name="@Exception" layout="${exception:tostring}" /> </target> </targets> <!-- 規則設定 --> <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" /> <!--這兩個規則一樣,也可以合併成一行,writeTo="ownFile-web, database"--> <logger name="*" minlevel="Trace" writeTo="database" /> </rules> </nlog>
基礎設定使用官方的即可,更進階的設定方法,官方也有提供文件
-
修改 ASP.NET Core program.cs 啟用 NLog
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
public static void Main(string[] args) { var logger = NLog.Web.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(Microsoft.Extensions.Logging.LogLevel.Trace); }) .UseNLog(); // NLog: Setup NLog for Dependency injection
-
設定 appsettings.json
ASP.NET Core 專案已經有基礎預設了,更進階的設定方法請參考,要特別留意,這邊的級別比nlog.config 高,也就是如果
Default
設定Information
,即使 nlog.config 的規則為 Trace,也無法寫入Debug 和 Trace 紀錄1 2 3 4 5 6 7 8 9 10 11
{ "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Trace", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*" }
-
測試寫入 Logs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public class HomeController : Controller { private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } public IActionResult Index() { _logger.LogTrace("Level 0 Trace"); _logger.LogDebug("Level 1 Debug"); _logger.LogInformation("Level 2 Information"); _logger.LogWarning("Level 3 Warning"); _logger.LogError("Level 4 Error"); _logger.LogCritical("Level 5 Critical"); return View(); } }
-
輸出結果
結論
NLog 簡單上手,較麻煩的反而是細節上的規則設定,過度的流水帳在追蹤問題時,是一種阻力,且在系統運作也會增加效能負擔,如何有效紀錄想要的東西更重要。
參考
.NET Core 與 ASP.NET Core 中的記錄
https://docs.microsoft.com/zh-tw/aspnet/core/fundamentals/logging/?view=aspnetcore-5.0
NLog Getting started with ASP.NET Core 3
https://github.com/NLog/NLog/wiki/Getting-started-with-ASP.NET-Core-3
NLog Database target
https://github.com/NLog/NLog/wiki/Database-target
NLog Configuration file