Util應用框架基礎(六) - 日志記錄(四) - 寫入 Exceptionless
本文是Util應用框架日志記錄的第四篇,介紹安裝和寫入 Exceptionless 日志系統的配置方法.
Exceptionless 是一個日志管理系統,使用 Asp.Net Core 開發,比 Seq 的模糊搜索能力弱,使用它可能需要一些技巧.
Util應用框架目前主要使用 Seq 和 Exceptionless 管理日志.
你可以從中選擇一個合適的.
本節介紹使用 Docker 簡單安裝 Exceptionless,用于開發測試,部署到生產環境請參考官方文檔.
安裝 Exceptionless
創建 exceptionless-data 卷, 運行命令.
docker volume create exceptionless-data
創建 Exceptionless 容器, 運行命令.
docker run --name exceptionless -d --restart=always -v exceptionless-data:/usr/share/elasticsearch/data -p 5480:80 exceptionless/exceptionless:8.0.0-elasticsearch7
容器名稱: exceptionless
連接端口: 5480
安裝成功后,Docker容器列表出現 exceptionless 容器.

運行 Exceptionless
打開 http://localhost:5480 ,可以看到 Exceptionless 管理界面.
Exceptionless 啟動需要一些時間,請稍后刷新頁面.
如果 Exceptionless 持續無法啟動,請刪除 exceptionless-data 卷,并重新安裝.

創建 Exceptionless 用戶
點擊 Signup 按鈕進入注冊頁面.

使用下面的信息注冊,或按你自己的喜好設置.
名稱: admin
郵箱: admin@a.com
密碼: admin123
點擊創建我的帳戶按鈕,進入管理界面.
創建 Exceptionless 項目
填寫組織名稱,范例: Util
填寫項目名稱,范例: Demo
點擊創建項目按鈕.
選擇頂部菜單的所有項目 ,點擊Demo項目設置按鈕.

在 Demo 項目設置界面,選擇 API密鑰 選項卡.

項目開發時,配置以下信息將日志寫入 Exceptionless.
API密鑰: 復制你的API密鑰,如上圖所示.
Exceptionless服務地址: http://localhost:5480
日志配置
-
引用Nuget包
Nuget包名: Util.Logging.Serilog.Exceptionless
-
AddExceptionless
使用 AddExceptionless 擴展方法啟用 Exceptionless 日志操作.
-
默認不帶參數,你可以在配置文件中指定 Exceptionless 的配置信息.
var builder = WebApplication.CreateBuilder( args ); builder.AsBuild().AddExceptionless(); -
如果要清除默認設置的日志提供程序,傳入 true.
Asp.Net Core 默認日志提供程序會把消息輸出到控制臺,你可以清除它們.
builder.AsBuild().AddExceptionless( true ); -
設置應用程序名稱.
對于微服務應用,記錄產生日志的應用名稱,能方便排查問題.
builder.AsBuild().AddExceptionless( "權限服務" ); -
指定Api密鑰和服務地址.
builder.AsBuild().AddExceptionless( t => { t.ApiKey = ""; t.ServerUrl = ""; } );指定Api密鑰和服務地址并清除默認設置的日志提供程序.
builder.AsBuild().AddExceptionless( t => { t.ApiKey = ""; t.ServerUrl = ""; }, true );
-
-
添加 appsettings 配置節
在 appsettings.json 配置文件添加 Exceptionless 配置節.
{ "Logging": { "LogLevel": { "Default": "Trace" } }, "Exceptionless": { "ApiKey": "8JtknZBV1NRC7bdsv6SF5cbBFrMZipWMkARZxkxo", "ServerUrl": "http://localhost:5480" } }ApiKey 指定 API 密鑰.
ServerUrl 指定 Exceptionless 服務地址.
最簡化配置僅需設置 API 密鑰和 Exceptionless 服務地址.
本教程 Exceptionless 安裝示例使用 5480 端口.
API 密鑰替換成你自己的.
其它參數請參考 Exceptionless 文檔.
查看 Exceptionless
配置完成后,可以啟動你的項目,查看 Exceptionless 日志界面.
可以看到由 Asp.Net Core 寫入的系統日志.

結構化日志支持
下面的示例比較結構化日志與普通日志的差別.
范例使用 ILog 接口寫入日志,你也可以使用 ILogger 替代.
先記錄普通日志消息,方便后續比較.
_log.Message( "用戶admin已刪除" ).LogInformation();

查看擴展屬性.

結構化日志語法
-
{}
-
{} 用來定義日志屬性.
-
范例:
_log.Message( "用戶{User}已刪除", "admin" ).LogInformation();{User} 定義了名為 User 的字符串屬性.
查看 Exceptionless 擴展屬性界面, 可以看到已經添加了 User 屬性.

識別出了 User 屬性,就可以使用它進行搜索.
搜索框輸入下面的表達式.
data.User:"admin"User 是一個擴展屬性,Exceptionless 要求擴展屬性前加上 data.
屬性名與屬性值使用 : 分隔,表示相等,即 屬性名=屬性值 .
字符串值可以放進雙引號中,比如 "admin"
字符串值也可不帶雙引號,比如 admin.
但是不能放在單引號中, 比如 'admin' .

Exceptionless 的模糊匹配能力有限,只支持頭匹配,類似 like 'xx%' ,不能完全模糊搜索.
Exceptionless 使用 * 進行模糊匹配,只能放在參數值右方, 比如 adm* .
帶 * 的參數值不能放在雙引號中 .
范例:
以 adm 開頭模糊搜索 User 擴展屬性.
data.User:adm*注意: 不要將結構化日志 {} 與 .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();
遺憾的是, Exceptionless 無法搜索對象屬性.
雖然 Exceptionless 對擴展屬性的搜索支持有限,但它內置了很多搜索語法,可以參考官方文檔.
-
-
-
{$} 用來定義日志屬性,并強制字符串化.
{$} 讓 Serilog 以明確的方式顯示對象的字符串表示.
var user = new User { Id = 1, Name = "a" }; _log.Message( "用戶{$User}已刪除", user ).LogInformation();{$User} 調用user對象的 ToString() 方法顯示為字符串.
-

浙公網安備 33010602011771號