本文是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() 方法顯示為字串.
-