如何在 ASP.NET Core 中使用 NLog 的高级特性
NLog 是一個開源的輕量級日志框架,提供了豐富的日志路由和管理功能,同時 NLog 也是非常容易的去配置和擴展,其實在之前的文章中我已經討論過了 Nlog,在這篇我準備繼續和大家討論一下 NLog 的更多高級功能。
接下來看看如何通過 .config 和 代碼方式 配置 NLog,如何去 輪轉日志,如何將 Log 對接 database,如何使用異步的模式提高日志寫入性能,同時我還會分享一些 NLog 的經驗技巧。
安裝 NLog
可以通過 NuGet Package Manager 可視化界面 或者 NuGet Package Manager Console 控制臺 安裝以下包文件。
NLog.Web.AspNetCore
NLog.Extensions.Logging
NLog.Config
當你安裝完 NLog.Config 之后,有一個叫做 NLog.config 文件會自動引用到你的項目中,值得注意的是,NLog.Config 對 NLog 來說不是唯一的,言外之意就是你即可以用 config 模式配置,也可以用 基于代碼 的模式配置。
使用 .config 文件配置 NLog
NLog 提供了兩種配置方式。
file-based 配置模式
code-based 配置模式
回到剛才的問題,如何采用 file-based 模式,剛才被引入的 NLog.Config 內容如下:
<?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"><extensions><add?assembly="NLog.Web.AspNetCore"/></extensions><targets><target?name="logfile"?xsi:type="File"?fileName="D:\logs\LogMessages-${shortdate}.log"?/></targets><rules><logger?name="*"?minlevel="Trace"?writeTo="logfile"?/></rules> </nlog>下面的代碼展示了如何在 Controller 下用 NLog 記錄日志。
public?class?HomeController?:?Controller{Logger?_logger?=?(Logger)LogManager.GetCurrentClassLogger(typeof(Logger));??public?IActionResult?Index(){_logger.Info("Application?started");???????return?View();}//Other?action?methods}如果你想通過編程的方式找到當前 NLog 的 target,可使用如下代碼:
var?fileTarget?=?(FileTarget)LogManager.Configuration.FindTargetByName("logfile");使用 代碼配置 NLog
同樣你也可以使用編碼的形式配置 NLog,只需要調用 NLog 提供的 API 接口即可,下面的代碼展示了如何配置 Nlog。
private?static?void?ConfigureNLog(){var?logConfiguration?=?new?LoggingConfiguration();var?dbTarget?=?new?DatabaseTarget();dbTarget.ConnectionString?=?"Data?Source=JOYDIP;initial?catalog=NLogDemo;User?Id=sa;Password=sa1@3#.;";?dbTarget.CommandText?=?"INSERT?INTO?DbLog?(level,?callsite,?message,?logdatetime)"?+"?Values(@level,?@callsite,?@message,?@logdatetime)";dbTarget.Parameters.Add(new?DatabaseParameterInfo("@level",?"${level}"));dbTarget.Parameters.Add(new?DatabaseParameterInfo("@callSite",?"${callSite}"));dbTarget.Parameters.Add(new?DatabaseParameterInfo("@message",?"${message}"));dbTarget.Parameters.Add(new?DatabaseParameterInfo("@logdatetime","${date:s}"));var?rule?=?new?LoggingRule("*",?LogLevel.Debug,?dbTarget);logConfiguration.LoggingRules.Add(rule);LogManager.Configuration?=?logConfiguration;}配置輪轉日志
你可以讓 NLog 自動實現 輪轉日志,什么叫 輪轉 呢?簡單來說就是:你可以讓 Nlog 只保存近 N 個小時的日志 并且自動刪除大于 N 小時的日志,這個特性太實用了,否則的話,你需要經常到生產上去刪除日志,下面的代碼展示了如何使用 .config 實現自動輪轉日志。
<?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"><targets><target?name="logfile"xsi:type="File"fileName="${basedir}/logs/App.log"layout="${longdate}??${message}"archiveFileName="${basedir}/logs/archive.{#}.log"archiveEvery="Day"archiveNumbering="Rolling"maxArchiveFiles="7"concurrentWrites="true"keepFileOpen="true"?/></targets><rules><logger?name="*"?minlevel="Info"?writeTo="logfile"?/></rules> </nlog>記錄日志到數據庫
創建數據庫
你可以使用 NLog 將日志接入到 database 中,下面的腳本用于創建幾張記錄日志的表。
CREATE?TABLE?[dbo].[DbLog]([Id]?[int]?IDENTITY(1,1)?NOT?NULL,[Level]?[varchar](max)?NULL,[CallSite]?[varchar](max)?NULL,[Message]?[varchar](max)?NULL,[AdditionalInfo]?[varchar](max)?NULL,[LogDateTime]?[datetime]?NOT?NULL,CONSTRAINT?[PK_DbLogs]?PRIMARY?KEY?CLUSTERED ([Id]?ASC )WITH?(PAD_INDEX?=?OFF,?STATISTICS_NORECOMPUTE?=?OFF,?IGNORE_DUP_KEY?=?OFF,?ALLOW_ROW_LOCKS?=?ON,?ALLOW_PAGE_LOCKS?=?ON)?ON?[PRIMARY] )?ON?[PRIMARY]?TEXTIMAGE_ON?[PRIMARY] GO數據庫連接串和參數屬性
接下來如何在 NLog 的 target 中指定數據庫連接串,請注意 connectionString 和 commandText 是如何配置的。
<target?name="database"?xsi:type="Database"?keepConnection="true"useTransactions="true"dbProvider="System.Data.SqlClient"connectionString="data?source=localhost;initialcatalog=NLogDemo;integrated?security=false;persist?security?info=True;User?ID=sa;Password=sa1@3#."commandText="INSERT?INTO?DbLog?(level,?callsite,?message,?additionalInfo,logdatetime)?Values?(@level,?@callsite,?@message,?@additionalInfo,@logdatetime)">使用參數化
最后,使用 參數化查詢 來防止注入攻擊,詳細代碼如下。
<parameter?name="@level"?layout="${level}"?/> <parameter?name="@callSite"?layout="${callsite}"?/> <parameter?name="@message"?layout="${message}"?/> <parameter?name="@additionalInfo"?layout="${var:AdditionalInfo}"?/> <parameter?name="@logdatetime"?layout="${date:s}"?/>完整的 NLog
以下是完整的 NLog 文件僅供參考。
<?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"><extensions><add?assembly="NLog.Web.AspNetCore"/></extensions><variable?name="AdditionalInfo"?value=""/>?<targets><target?name="database"?xsi:type="Database"?keepConnection="true"useTransactions="true"dbProvider="System.Data.SqlClient"connectionString="data?source=localhost;initialcatalog=NLogDemo;integrated?security=false;persist?security??info=True;User?ID=sa;Password=sa1@3#."commandText="INSERT?INTO?DbLog(level,?callsite,?message,?additionalInfo,?logdatetime)Values?(@level,?@callsite,?@message,?@additionalInfo,?@logdatetime)"><parameter?name="@level"?layout="${level}"?/><parameter?name="@callSite"?layout="${callsite}"?/><parameter?name="@message"?layout="${message}"?/><parameter?name="@additionalInfo"?layout="${var:AdditionalInfo}"?/><parameter?name="@logdatetime"?layout="${date:s}"?/></target>???????</targets><rules><logger?levels="Debug,Info,Error,Warn,Fatal"?name="databaseLogger"?writeTo="database"/></rules> </nlog>除了 SQL Server 之外,還可以使用 NLog 將日志記錄到 MySQL,Oracle 和 SQLite 數據庫。
使用 AsyncWrapper 提高性能
NLog 支持多種 targets,比如:AsyncWrapper, BufferingWrapper, FallbackGroup 和 RetryingWrapper,異步的 target 為了提升性能采用 消息的隊列化 并在多個線程中提取隊列消息,下面的代碼展示了如何使用 AsyncWrapper。
<targets><target?xsi:type="AsyncWrapper"name="String"queueLimit="Integer"timeToSleepBetweenBatches="Integer"batchSize="Integer"overflowAction="Enum"><target?...?/></target> </targets>你可以實現 AsyncWrapper 來實現日志記錄的異步化,詳細配置如下:
<targets><target?name="asyncFile"?xsi:type="AsyncWrapper"><target?xsi:type="File"?name="fileLog"fileName="${basedir}/Logs/${shortdate}.log"layout="${longdate}?${uppercase:${level}}?${message}"/></target></targets><rules><logger?levels="Debug,Info,Error,Warn,Fatal"?writeTo="asyncFile"/></rules>除了這種方式,你還可以在所有的 targets 上用 async=true 直接進行標記為異步化 target,如下配置所示:
<targets?async="true">...?Write?your?targets?here?... </targets>NLog 的最佳實踐
這一小節列舉了一些使用 NLog 的一些最佳實踐
logger 實例應該靜態化,這樣就可以避免在程序中出現多次 logger 初始化帶來的性能開銷。
利用好 NLog 的 Format(當你想結構化日志)支持,避免你自己對 string 的創建和拼接。
指定 throwConfigExceptions="true" ,可以確保當 NLog 配置錯誤的時候有詳細的錯誤信息,例子如下:
當記錄完日志后,可以調用 LogManager.Shutdown() 來實現數據刷新并且關閉內部所有的線程和定時器。
不要將 async 屬性用在 AsyncWrapper 之上,否則性能會變慢。
慎用 Trace 級別,因為 Trace 會記錄所有的日志,考慮使用 Debug 或者 Info 代替。
NLog 是輕量級并且快速的,可以使用 asynchronous wrappers 的方式來提升性能。
關于 NLog 還是有太多的話要說,NLog 提供了日志的結構化,方便在大量日志上進行快速過濾和分析,在未來的文章中我會討論 NLog 的更多高級特性。
譯文鏈接:https://www.infoworld.com/article/3438540/using-advanced-nlog-features-in-aspnet-core.html
總結
以上是生活随笔為你收集整理的如何在 ASP.NET Core 中使用 NLog 的高级特性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对CORS OPTIONS预检请求的一些
- 下一篇: ASP.NET Core Control