本文是Util應用框架紀錄檔記錄的第三篇,介紹安裝和寫入 Seq 紀錄檔系統的設定方法.
Seq是一個紀錄檔管理系統,對結構化紀錄檔資料擁有強大的模糊搜尋能力.
Util應用框架目前主要使用 Seq 和 Exceptionless 管理紀錄檔.
你可以從中選擇一個合適的.
本節介紹使用 Docker 簡單安裝 Seq,用於開發測試,部署到生產環境請參考官方檔案.
建立 seq-data 卷, 執行命令.
docker volume create seq-data
建立 Seq 容器, 執行命令.
docker run --name seq -d --restart=always -e ACCEPT_EULA=Y -v seq-data:/data -p 5380:80 datalust/seq:2023.3
容器名稱: seq
連線埠: 5380
未設定使用者密碼
安裝成功後,Docker容器列表出現 seq 容器.
開啟 http://localhost:5380 ,可以看到 Seq 管理介面.
Nuget包名: Util.Logging.Serilog
使用 AddSerilog 擴充套件方法啟用 Serilog 紀錄檔操作.
預設設定不帶引數.
var builder = WebApplication.CreateBuilder( args );
builder.AsBuild().AddSerilog();
如果要清除預設設定的紀錄檔提供程式,傳入 true.
Asp.Net Core 預設紀錄檔提供程式會把訊息輸出到控制檯,你可以清除它們.
builder.AsBuild().AddSerilog( true );
設定應用程式名稱.
對於微服務應用,記錄產生紀錄檔的應用名稱,能方便排查問題.
builder.AsBuild().AddSerilog( "許可權服務" );
你也可以使用委託設定引數.
builder.AsBuild().AddSerilog( t => t.IsClearProviders = true );
在 appsettings.json 組態檔新增 Serilog 設定節.
{
"Logging": {
"LogLevel": {
"Default": "Trace"
}
},
"Serilog": {
"WriteTo": [
{
"Name": "Seq",
"Args": {
"serverUrl": "http://localhost:5380"
}
}
]
}
}
WriteTo 指定紀錄檔接收器為 Seq.
最簡化設定僅需設定 Seq 的服務地址.
本教學 Seq 安裝範例使用 5380 埠.
其它引數請參考 Serilog 和 Seq 檔案.
設定完成後,可以啟動你的專案,檢視 Seq 紀錄檔介面.
可以看到由 Asp.Net Core 寫入的系統紀錄檔.
下面的範例比較結構化紀錄檔與普通紀錄檔的差別.
範例使用 ILog 介面寫入紀錄檔,你也可以使用 ILogger 替代.
先記錄普通紀錄檔訊息,方便後續比較.
_log.Message( "使用者admin已刪除" ).LogInformation();
{}
{} 用來定義紀錄檔屬性.
範例:
_log.Message( "使用者{User}已刪除", "admin" ).LogInformation();
{User} 定義了名為 User 的字串屬性.
檢視 Seq 操作介面, 可以看到已經新增了 User 屬性.
識別出了 User 屬性,就可以使用它進行搜尋.
點選 User 屬性左側的勾,彈出選單選擇 Find 進行查詢.
搜尋方塊設定 User = 'admin' 表示式,表示搜尋 User 屬性為 admin 的紀錄檔.
Seq 不僅能使用 = 進行精確匹配,還支援類似Sql like 的模糊匹配方式.
範例:
User like '%dm%'
注意: 不要將結構化紀錄檔 {} 與 .Net 字串語法 $"{}" 混淆.
var user = "admin";
_log.Message( $"使用者{user}已刪除" ).LogInformation();
$"" 中的 {user} 將被 user 變數值 'admin' 替換, 等效於.
_log.Message( "使用者admin已刪除" ).LogInformation();
它僅是普通紀錄檔訊息,不是結構化紀錄檔.
{@} 用來定義紀錄檔屬性,並強制序列化物件.
前面的範例使用簡單的字串引數,如果傳入物件引數是什麼結果?
範例:
定義 User 物件.
namespace Demo;
public class User {
public int Id { get; set; }
public string Name { get; set; }
}
現在傳入 User 物件.
var user = new User { Id = 1, Name = "a" };
_log.Message( "使用者{User}已刪除", user ).LogInformation();
{User} 被替換為字串 "Demo.User" ,這是通過呼叫 User 物件的 ToString() 方法得到的.
這與我們的預期不符合,我們希望序列化 User 物件,從而獲取物件的結構進行搜尋.
Serilog 對 {} 引數的處理有一套內建規則,如果傳入物件,有些結構能序列化,比如字典 Dictionary<string,int> ,有些則不能.
不應該依賴 Serilog 自動序列化的能力,而是應明確指定是否序列化.
{@} 強制序列化物件,從而保留物件結構,以方便紀錄檔系統展示和搜尋.
var user = new User { Id = 1, Name = "a" };
_log.Message( "使用者{@User}已刪除", user ).LogInformation();
可以進一步展開物件結構,點選 {Id: 1, Name: 'a'} 左側的小燈泡,選擇 Expand all 展開.
現在可以通過物件屬性進行搜尋了.
{$} 用來定義紀錄檔屬性,並強制字串化.
{$} 讓 Serilog 以明確的方式顯示物件的字串表示.
var user = new User { Id = 1, Name = "a" };
_log.Message( "使用者{$User}已刪除", user ).LogInformation();
{$User} 呼叫user物件的 ToString() 方法顯示為字串.