.NET Core开发日志——结构化日志
在.NET生態(tài)圈中,最早被廣泛使用的日志庫(kù)可能是派生自Java世界里的Apache log4net。而其后來(lái)者,莫過(guò)于NLog。Nlog與log4net相比,有一項(xiàng)較顯著的優(yōu)勢(shì),它支持結(jié)構(gòu)化日志。
結(jié)構(gòu)化日志,也被稱為語(yǔ)義化日志。其作用有二,利于查詢與方便分析。
當(dāng)系統(tǒng)上線被廣泛使用或者時(shí)間久遠(yuǎn)之后,日志的大量出現(xiàn)不可避免。且日志本身作為一種數(shù)據(jù),也有其重要的價(jià)值。因此,如何有效地對(duì)其進(jìn)行查詢以及最大價(jià)值化地分析處理便成了一個(gè)重要的問(wèn)題。
非結(jié)構(gòu)化日志
對(duì)于日志的處理,需要權(quán)衡對(duì)開(kāi)發(fā)者的友好性與對(duì)程序解析的方便性。傳統(tǒng)的非結(jié)構(gòu)化日志更傾向于前者。當(dāng)開(kāi)發(fā)者想要記錄一段日志時(shí),他可以很簡(jiǎn)單地加上一行代碼,即可達(dá)成其目的。
logger.Info("Logon by user:{0} from ip_address:{1}", "Kenny", "127.0.0.1");然后這行代碼的執(zhí)行結(jié)果可能被存于文本文件或者數(shù)據(jù)庫(kù)中。
2018-12-22 16:29:29.2793|Info|Logon by user:Kenny from ip_address:127.0.0.1這樣的日志以開(kāi)發(fā)者的角度來(lái)看,清晰易懂,十分友好。但如果要使用程序去查找海量的上述例子里的某段時(shí)間內(nèi)的特定登陸用戶,則很難高效地完成這一要求,因?yàn)樾枰獙?duì)每個(gè)日志進(jìn)行字符串解析。
消息模板
消息模板規(guī)范是結(jié)構(gòu)化日志的通用語(yǔ)法,其是一個(gè)與開(kāi)發(fā)語(yǔ)言無(wú)關(guān)的規(guī)范,能以特定格式捕獲及呈現(xiàn)結(jié)構(gòu)化日志,同時(shí)提供對(duì)開(kāi)發(fā)者與程序解析的友好支持。
以上圖片中的日志記錄方式乍看起來(lái)與非結(jié)構(gòu)化日志差不多,但它們之間具有本質(zhì)的區(qū)別,在結(jié)構(gòu)化日志里,是以對(duì)象而非字符串處理日志內(nèi)容的。
如果將非結(jié)構(gòu)化日志例子里的代碼改成結(jié)構(gòu)化日志的寫(xiě)法。
logger.Info("Logon by {user} from {ip_address}", "Kenny", "127.0.0.1");執(zhí)行后兩者的結(jié)果是這樣的:
2018-12-22 16:29:29.2793|Info|Logon by user:Kenny from ip_address:127.0.0.1 2018-12-22 16:29:29.2976|Info|Logon by "Kenny" from "127.0.0.1"似乎差別并不大,再將輸出類(lèi)型改成JSON風(fēng)格看看:
{ "time": "2018-12-22 16:30:15.1314", "level": "INFO", "message": "Logon by user:Kenny from ip_address:127.0.0.1" } { "time": "2018-12-22 16:30:15.1569", "level": "INFO", "message": "Logon by \"Kenny\" from \"127.0.0.1\"", "user": "Kenny", "ip_address": "127.0.0.1" }顯而易見(jiàn),對(duì)于后者,因?yàn)閡ser被作為對(duì)象的屬性獨(dú)立分離出來(lái),在做程序處理時(shí),可以很方便地以其為條件進(jìn)行篩選。這對(duì)于查詢或者分析日志是極為重要的。
NLog
NLog中對(duì)于結(jié)構(gòu)化日志的支持是在4.5版本才開(kāi)始的。這一改動(dòng)并不會(huì)破壞原有的代碼,而如果想要使用新的特性,則只要用符合消息模板的語(yǔ)法編寫(xiě)所需的代碼即可。
代碼的格式化結(jié)果依據(jù)數(shù)據(jù)的類(lèi)型而定。
字符串類(lèi)型將被雙引號(hào)包圍
數(shù)值類(lèi)型沒(méi)有引號(hào)
null顯示為NULL
列表或數(shù)組類(lèi)型,以逗號(hào)分隔,例如:"item1", "item2"
字典類(lèi)型,健與值之間用等號(hào)相聯(lián),例如:"key1"="value1", "key2"="value2"
對(duì)象類(lèi)型,調(diào)用ToString方法顯示結(jié)果
此外,還可以有@與$符號(hào):
@ 以JSON格式格式化數(shù)據(jù)
$ 強(qiáng)制調(diào)用ToString方法
而將日志輸出格式改成JSON的方法,是在NLog.config配置文件里將布局切換成JsonLayout類(lèi)型,同時(shí)設(shè)置includeAllProperties為true,以顯示所有對(duì)象屬性。
<target name="console" xsi:type="Console"><layout xsi:type="JsonLayout" includeAllProperties="true"><attribute name="time" layout="${longdate}" /><attribute name="level" layout="${level:upperCase=true}"/><attribute name="message" layout="${message}" /></layout></target>Serilog
能夠?qū)崿F(xiàn)結(jié)構(gòu)化日志的類(lèi)庫(kù)除了NLog之外,其它較常用的當(dāng)屬Serilog。
與NLog相比,Serilog省去了配置文件,直接使用代碼,實(shí)現(xiàn)方式更加簡(jiǎn)潔。
執(zhí)行結(jié)果:
{"Timestamp":"2018-12-22T17:15:23.6389082+08:00","Level":"Information","MessageTemplate":"Processed {@Position} in {Elapsed:000} ms.","Properties":{"Position":{"Latitude":25,"Longitude":134},"Elapsed":34},"Renderings":{"Elapsed":[{"Format":"000","Rendering":"034"}]}}原文地址:https://www.cnblogs.com/kenwoo/p/9906185.html
.NET社區(qū)新聞,深度好文,歡迎訪問(wèn)公眾號(hào)文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的.NET Core开发日志——结构化日志的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: .NET Core 和 DevOps
- 下一篇: 迎元旦,庆surging 1.0发布