Util應用框架基礎(六) - 日志記錄(三) - 寫入 Seq
本文是Util應用框架日志記錄的第三篇,介紹安裝和寫入 Seq 日志系統的配置方法.
安裝 Seq
Seq是一個日志管理系統,對結構化日志數據擁有強大的模糊搜索能力.
Util應用框架目前主要使用 Seq 和 Exceptionless 管理日志.
你可以從中選擇一個合適的.
本節介紹使用 Docker 簡單安裝 Seq,用于開發測試,部署到生產環境請參考官方文檔.
安裝 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 容器.

運行 Seq
打開 http://localhost:5380 ,可以看到 Seq 管理界面.

寫入 Seq
日志配置
-
引用Nuget包
Nuget包名: Util.Logging.Serilog
-
AddSerilog
使用 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 配置節
在 appsettings.json 配置文件添加 Serilog 配置節.
{ "Logging": { "LogLevel": { "Default": "Trace" } }, "Serilog": { "WriteTo": [ { "Name": "Seq", "Args": { "serverUrl": "http://localhost:5380" } } ] } }WriteTo 指定日志接收器為 Seq.
最簡化配置僅需設置 Seq 的服務地址.
本教程 Seq 安裝示例使用 5380 端口.
其它參數請參考 Serilog 和 Seq 文檔.
查看 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() 方法顯示為字符串.
-

浙公網安備 33010602011771號