在 .NET 使用日誌框架第一時間會想到 NLog 或是 Log4Net 兩種 Log 常使用的 Library,Serilog 是這幾年快速崛起的 Log 框架之一,Serilog 是以 Structured logging 為基礎進行設計,透過 logging API 可以輕鬆的記錄應用程式中對象屬性,方便快速進行 logging 內容進行查詢與分析,並將其紀錄內容透過 json (可指定) 的方式輸出,這篇就介紹 Serilog 在 ASP.NET Core 中如何的安裝與基本應用使用,若有問題或是錯誤的地方歡迎網路的高手大大給予指導。
Serilog 支援 NET Framework 與 NET Core 版本,使用前需要透過 Nuget 進行下載的動作,首先先建立一個名稱為 SerilogLab 的 Console 專案,接著開啟 Nuget Package Manager (快速打開方法: Ctrl + Q ) 輸入 "Serilog" 搜尋,安裝最新版的 serilog 套件
或是在 Nuget Package Console 輸入指令,下載核心項目 Serilog 與需要用到的 Logging Sinks
PM> Install-Package Serilog PM> Install-Package Serilog.Sinks.Console確認是否有安裝成功,可以點擊專案檔內容是否包含以下 package
<PackageReference Include="Serilog" Version="2.8.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
Logging Sinks
Serilog 核心負責紀錄 Log 事件的內容,如果要將 Log 輸出則是透過 Snik (槽),Serilog 最常見的是 console 與 file 檔案兩種 sink,另外提供不同的輸出方式如Amazon、Azure、Elasticsearch、Slack等多樣,需要使用時要在 nuget 下載 Sinks library 另外官方也有整理目前支援的 sinks 清單 : 傳送門,有興趣可以自行查閱。
使用
接著在 Console 專案 Program 啟動加入下列代碼
using System; using Serilog; namespace SerilogLab { class Program { static void Main(string[] args) { var log = new LoggerConfiguration() .WriteTo.Console() .CreateLogger(); log.Information("Hello, Serilog!"); log.Debug("This is debug"); log.Error("Something error"); log.Fatal("This is fatal"); Console.ReadKey(); } } }程式說明
Log
在 Serilog 中提供靜態 Log 讓開發者使用,有時在開發時會在建構子注入 logging 物件方便記錄,舉例來說常常可以看到在 Controller、service 或是 repository 上建構子注入 ILog 的 interface,可以透過以下方式統一建立 Log 實體存放在 Serilog Log 的 Static Logger 中,代碼如下
Log.Logger = new LoggerConfiguration() .WriteTo.Console() .CreateLogger(); Log.Information("Hello, Serilog by Log!");輸出如下,與一般輸出是相同的
注意 : 使用 Static 的方式缺點就是在測試時會造成不便,因此可以依據需求來決定是否需要使用
結構化日誌
為了瞭解 Serilog 背後的設計理念與原由,作者 Nicholas Blumhardt 在個人部落格寫了一系列相關文章來說明設計概念,以下為小弟粗淺的整理文章重點,想了解更多的朋友也請透過文章傳送門自行服用內容 : Structured logging concepts in .NET Series ,在應用程式紀錄 Log 時,大致來說紀錄方式可以分為 Text logging 也是一般常見的 log 檔記錄方式 與 Structured logging 與結構化的方式記錄 Log
Text logging :
12:23:10 [INF] Service "loyalty-card-printer" starting up on host 8fd342hkg22u 12:23:11 [INF] Listening on http://8fd342hkg22u.example.com:1234 12:40:55 [INF] Card replacement request received for customer-98048 …內容清楚且容易閱讀,清楚紀錄發生的時間點、問題層級以及內容資訊,呈現格式對開發者閱讀是方便地但如果搜尋 Log 內容時則需使用全文檢索或是正規表達式進行 parse 的動作,才可以找到正確的資訊。
Structured logging :
time=12:23:11, level=INF, endpoint=http://8fd342hkg22u.example.com:1234, activity=listening time=12:23:20, level=INF, customer=customers-1099972, activity=replacement time=12:40:55, level=INF, customer=customer-98048, activity=replacement …時間戳記加上其屬性值 key / value 的組合,透過結構化的方式可以讓 Log 更容易得讓機器閱讀,更方便於大規模的搜尋與分析。其 logging 規範名為 message template,同時滿足開發者閱讀方便性與機器可解讀格式,下圖為 message template 概念的示意圖
碎碎念 : 好的 Log 設計與監控可以讓問題快速被定位,而不是讓 oncall 同仁透過觀落陰解決。
結構化數據
一開始有輸出 Hello Serilog 簡單提到 serilog 基本使用方式,接著在說明 serilog 結構化資料的方法,下面範例是使用 Serilog information 方法紀錄 var 與集合 fruit 內容
// var var count = 456; log.Information("Retrieved {Count} records", count); // Collections var fruit = new[] { "Apple", "Pear", "Orange" }; log.Information("In my bowl I have {Fruit}", fruit);上面代碼 Console 輸出如下
[11:30:59 INF] Retrieved 456 records [11:30:59 INF] In my bowl I have ["Apple", "Pear", "Orange"]Serilog 可以將事件的屬性記錄到 Log 中,舉例來說如果希望輸出為 Json 格式取代既有的 txt 檔案 (也可輸出其他格式),可以指定其 formatter 並載入 Serilog.Formatting.Compact 設定格式化設定,即可將輸出內容轉為 json 檔案
var log = new LoggerConfiguration() .WriteTo.Console() .WriteTo.File(new CompactJsonFormatter(), "log.txt") .CreateLogger();原本範例 count 會加上屬性,時間會加上@t,並輸出定義的模板(message template) @mt 及參數內容
{ "@t": "2019-05-01T03:30:59.7633809Z", "@mt": "Retrieved {Count} records", "Count": 456 }另一個範例 fruit 輸出如下
{ "@t": "2019-05-01T03:30:59.8247590Z", "@mt": "In my bowl I have {Fruit}", "Fruit": [ "Apple", "Pear", "Orange" ] }關於 Serilog 的輸出格式就先介紹到這裡,詳細更多細節可以參考官方網站詳細介紹 : Formatting Output
感想
這篇針對 Serilog 的設計概念與基本使用進行了簡單的介紹,相信在使用上對大家來說難度都不高,自己在新專案上也有導入,之後有時間會在介紹一些關於設定與實作的細節部分,最後推薦對於結構化紀錄有興趣的可以參考作者的部落格介紹 Structured logging concepts in .NET Series,相信可以對於相關知識有更進一步的了解,也可以在.NET Framework 或是 ASP.NET Core 選擇 Logging 時有不一樣的選擇 :)
參考
Structured logging concepts in .NET Series
0 意見:
張貼留言