拥抱.NET Core系列:Logging (1)
在之前我們簡單介紹了 .NET Core 中的 DI組件,沒來及了解的童鞋可以翻翻我之前的文章。
接下來會(huì)對 .NET Core 中的 Logging 進(jìn)行介紹。
本文中使用了“Microsoft.Extensions.Logging.Console”做為輸出目標(biāo),后續(xù)文章會(huì)詳解。
Logging 中的三劍客
可以看到 Logging 的核心抽象就是三個(gè)接口,分別是:
ILogger:負(fù)責(zé)具體的日志寫入邏輯,如:FileLogger,ConsoleLogger,SQLLogger,ElasticsearchLogger 等。
ILoggerProvider:用來創(chuàng)建記錄器,一般和Logger配套使用,相當(dāng)于單個(gè)Logger類型的工廠接口。
ILoggerFactory:記錄器工廠,直接面向使用者的,使用者可以通過記錄器工廠添加記錄器提供程序和創(chuàng)建記錄器。
這幾個(gè)核心抽象位于 NuGet包:“Microsoft.Extensions.Logging.Abstractions”中。
日志等級
在.NET Core提供的日志抽象中提供了7個(gè)日志等級(比一般的日志組件多提供了一個(gè)Trace和None),分別是:
Trace
包含最詳細(xì)消息的日志。 這些消息可能包含敏感的應(yīng)用程序數(shù)據(jù)。 默認(rèn)情況下禁用這些消息,并且不應(yīng)在生產(chǎn)環(huán)境中啟用這些消息。
Debug
在開發(fā)過程中用于交互式調(diào)查的日志。 這些日志應(yīng)主要包含對調(diào)試有用的信息,不具有長期價(jià)值。
Information
跟蹤應(yīng)用程序的一般流程的日志。 這些日志應(yīng)具有長期價(jià)值。
Warning
突出顯示應(yīng)用程序流中異常或意外事件的日志,但是否則不會(huì)導(dǎo)致應(yīng)用程序執(zhí)行停止。
Error
當(dāng)當(dāng)前執(zhí)行流程由于失敗而停止時(shí),會(huì)突出顯示的日志。這些應(yīng)該指示當(dāng)前活動(dòng)中的故障,而不是應(yīng)用程序范圍的故障。
Critical
描述不可恢復(fù)的應(yīng)用程序或系統(tǒng)崩潰或?yàn)?zāi)難性的日志失敗需要立即關(guān)注。
None
不用于寫日志消息。 指定記錄類別不應(yīng)寫任何消息。
簡單的使用
CreateLogger 方法
CreateLogger 方法的簽名為
它提供了兩個(gè)擴(kuò)展方法,可以通過類型作為分類名稱,如下:
如何根據(jù)類型確定分類名稱?
在擴(kuò)展方法內(nèi)部使用了“GetTypeDisplayName(Type type)”來根據(jù)類型獲取名稱(里面有一些邏輯處理,但一般是采用“{命名空間}.{類型名稱}”作為分類名稱)。
實(shí)現(xiàn)傳送門:https://github.com/aspnet/Logging/blob/patch/1.1.3/src/Microsoft.Extensions.Logging.Abstractions/Internal/TypeNameHelper.cs
Log方法
logLevel
日志等級,詳情見上文。
eventId(結(jié)構(gòu)體,必填,可以傳入 0 或 default(EventId)來充當(dāng)默認(rèn)值)
事件ID。
這邊的事件ID是用來追蹤的,類似 ErrorCode、StatusCode。這樣在日志檢索的時(shí)候可以通過code很方便的找到。
是一個(gè)結(jié)構(gòu)體,默認(rèn)為:“0”。
state(可為null)
狀態(tài)。
需要記錄的對象,這邊可以傳入任何類型,這就有點(diǎn)奇怪了日志不都是字符嗎?
如果我傳一個(gè)自建類 UserModel 進(jìn)去會(huì)記錄出什么信息呢?請接下來看 formatter 參數(shù)。
exception(可為null)
異常。
不多說了,如果當(dāng)前上下文有異常,你丟進(jìn)去就好了。
formatter(不可為null)
格式化器。
這個(gè)參數(shù)是一個(gè)委托可以看到定義“Func<TState,Exception,string>”,這個(gè)就可以解釋state是非字符的情況下如何記錄日志了。
這邊可以通過你自己的邏輯來重建消息的內(nèi)容(異常信息都會(huì)進(jìn)行輸出)。
如果傳入null,日志組件會(huì)使用默認(rèn)的格式化器替換,默認(rèn)的格式化器邏輯是調(diào)用“state.ToString()”
擴(kuò)展方法
當(dāng)然Logging組件為我們提供了大量擴(kuò)展方法以簡化我們的編碼。
以下是方法存根,參數(shù)說明可以對照上文。
EventId效果
日志域
日志域可以聚合一類的消息,非常適合同一種類型不同維度的日志記錄。
日志過濾器
Logging提供了一個(gè)包裝實(shí)現(xiàn)用來實(shí)現(xiàn)日志過濾,我們先來看看使用。
可以看到可以通過制定 CategoryName 及最小日志等級來控制日志是否輸出,這邊有個(gè)有趣的事情。
就是 CategoryName 可以模糊匹配。
在 Logging 組件內(nèi)部擋識(shí)別到 CategoryName 為:“ConsoleApp.MyClass”時(shí)會(huì)把這個(gè)分類名稱分割為:
“ConsoleApp.MyClass”
“ConsoleApp”
ps:如果你的命名空間中存在多個(gè)“.”符號則還會(huì)被分割。
分割完成之后會(huì)將這些 Key 拿去與“FilterLoggerSettings”中的字典表進(jìn)行匹配,優(yōu)先最大匹配,也就是說如果我們配置了“ConsoleApp.MyClass”這條項(xiàng)目,則優(yōu)先使用這條,否則繼續(xù)尋找“ConsoleApp”這條項(xiàng)目,如果都沒匹配到則使用默認(rèn)的規(guī)則。
實(shí)現(xiàn)傳送門:https://github.com/aspnet/Logging/blob/patch/1.1.3/src/Microsoft.Extensions.Logging.Filter/Internal/FilterLogger.cs
在 NLog、log4jnet 等組件中模糊匹配是采用“.*”的方式,例如:”ConsoleApp.*”,在 .NET Core 中的 Logging 中是不被支持的(把“.*”去掉實(shí)現(xiàn)相同的效果),這點(diǎn)需要注意。
注意
“.WithFilter”是使用包裝的方式進(jìn)行集成,所以內(nèi)部會(huì)單獨(dú)維護(hù)一個(gè) FilterLogger,也就意味著所有的 LoggerProvider 必須在 FilterFactory 中進(jìn)行注冊,不然過濾器是不會(huì)生效的哦。以下是錯(cuò)誤的示例:
紅色框框部分的兩句應(yīng)該對調(diào),“.WithFilter”應(yīng)該優(yōu)先調(diào)用。
特殊的Logger => NullLogger
這個(gè)我覺得 .NET Core 是從 Orchard“偷”過來的,Orchard 滿地的 NullLogger.Instance。
為什么需要 NullLogger?
在業(yè)務(wù)系統(tǒng)中,Logger 其實(shí)并不影響邏輯,換句話說,Logger如果失敗不應(yīng)該影響業(yè)務(wù)。
在單元測試時(shí) Logger 也可以忽略。
這句話肯定是對的,但在遍地DI的項(xiàng)目中 Logger 很有可能被開發(fā)者傳入null,這時(shí)候就會(huì)影響業(yè)務(wù)的執(zhí)行,那么這時(shí)候 NullLogger 非常適合做那個(gè)最糟糕的實(shí)現(xiàn)者。
用來替換日志記錄或防止“NullReferenceException”這類異常的發(fā)生。
非常可惜的是,1.1.3版本中沒有提供 NullLogger<T> 這樣的實(shí)現(xiàn)。好消息是在 .NET Standard2.0 中已經(jīng)提供了 NullLogger<T> 的實(shí)現(xiàn)。
我們下面來看看可使用的場景:
可以看到在沒有添加 Logging 組件的時(shí)候日志記錄也不會(huì)拋出異常。
ps:NullLogger<T> 摘抄至.NET Standard2.0中的 NullLoggerOfT.cs。
地址:https://github.com/aspnet/Logging/blob/dev/src/Microsoft.Extensions.Logging.Abstractions/NullLoggerOfT.cs
Logger in DependencyInjection
不使用 Filter
使用 Filter
寫在最后
不得不感嘆微軟在 .NET Core 中統(tǒng)一了非常多的常用組件,為開發(fā)者統(tǒng)一環(huán)境提供了極大的方便。
后續(xù)的文章會(huì)分享如何集成第三方 Logging 組件,比如:NLog、log4jnet、Exceptionless 等。
.NET技術(shù)棧QQ群:384413261(點(diǎn)擊加入 .NET Group)
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的拥抱.NET Core系列:Logging (1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Prometheus 入门
- 下一篇: ubuntu中怎么安装Kdevelop