本文是Util應用框架紀錄檔記錄的第四篇,介紹安裝和寫入 Exceptionless 紀錄檔系統的設定方法.
Exceptionless 是一個紀錄檔管理系統,使用 Asp.Net Core 開發,比 Seq 的模糊搜尋能力弱,使用它可能需要一些技巧.
Util應用框架目前主要使用 Seq 和 Exceptionless 管理紀錄檔.
你可以從中選擇一個合適的.
本節介紹使用 Docker 簡單安裝 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 容器.
開啟 http://localhost:5480 ,可以看到 Exceptionless 管理介面.
Exceptionless 啟動需要一些時間,請稍後重新整理頁面.
如果 Exceptionless 持續無法啟動,請刪除 exceptionless-data 卷,並重新安裝.
點選 Signup 按鈕進入註冊頁面.
使用下面的資訊註冊,或按你自己的喜好設定.
名稱: admin
密碼: admin123
點選建立我的帳戶按鈕,進入管理介面.
填寫組織名稱,範例: Util
填寫專案名稱,範例: Demo
點選建立專案按鈕.
選擇頂部選單的所有專案 ,點選Demo專案設定按鈕.
在 Demo 專案設定介面,選擇 API金鑰 索引標籤.
專案開發時,設定以下資訊將紀錄檔寫入 Exceptionless.
API金鑰: 複製你的API金鑰,如上圖所示.
Exceptionless服務地址: http://localhost:5480
Nuget包名: Util.Logging.Serilog.Exceptionless
使用 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.json 組態檔新增 Exceptionless 設定節.
{
"Logging": {
"LogLevel": {
"Default": "Trace"
}
},
"Exceptionless": {
"ApiKey": "8JtknZBV1NRC7bdsv6SF5cbBFrMZipWMkARZxkxo",
"ServerUrl": "http://localhost:5480"
}
}
ApiKey 指定 API 金鑰.
ServerUrl 指定 Exceptionless 服務地址.
最簡化設定僅需設定 API 金鑰和 Exceptionless 服務地址.
本教學 Exceptionless 安裝範例使用 5480 埠.
API 金鑰替換成你自己的.
其它引數請參考 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() 方法顯示為字串.