Serilog文件翻譯系列(三) - 基礎配置

IT规划师發表於2024-09-01

Serilog 使用簡單的 C# API 來配置日誌記錄。當需要外部配置時,可以(慎用)透過使用 Serilog.Settings.AppSettings 包或 Serilog.Settings.Configuration 包進行混合配置。

建立日誌記錄器

日誌記錄器是透過 LoggerConfiguration 物件建立的:

Log.Logger = new LoggerConfiguration().CreateLogger();
Log.Information("No one listens to me!");
// Finally, once just before the application exits...
Log.CloseAndFlush();

上面的示例將建立一個不記錄任何事件的日誌記錄器。要檢視日誌事件,必須配置一個接收器。

接收器

日誌事件接收器通常將日誌事件記錄到某些外部表示形式中,最常見的是控制檯、檔案或資料儲存。Serilog 的接收器透過 NuGet 分發。在 Wiki 上,有一個精心整理的可用接收器列表。

這個示例將使用控制檯接收器包和檔案接收器包,控制檯接收器包用於格式化日誌資料輸出到控制檯,檔案接收器包用於將日誌事件寫入一組按日期標記的文字檔案。

$ dotnet add package Serilog.Sinks.Console
$ dotnet add package Serilog.Sinks.File

接收器透過 WriteTo 配置物件進行配置。

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
.CreateLogger();
Log.Information("Ah, there you are!");

多個接收器可以同時啟用。如果需要新增額外的接收器可以透過鏈式呼叫 WriteTo 塊來實現:

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.File("log-.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

輸出模板

基於文字的接收器使用輸出模板來控制格式。可以透過 outputTemplate 引數進行修改:

.WriteTo.File("log.txt",outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")

上面的示例中展示的預設模板使用了內建的屬性,如 Timestamp 和 Level。來自事件的屬性,包括使用增強器附加的屬性,也可以出現在輸出模板中。

{Message:lj} 格式選項使訊息中的資料以 JSON 格式(j)輸出,但字串文字會原樣輸出。

新增 {Properties:j} 到輸出模板中,以包括額外的上下文資訊。

在輸出模板中新增 {Properties:j} 可以包含額外的上下文資訊。這允許你將與日誌事件相關聯的所有屬性(包括自定義屬性)以 JSON 格式輸出到日誌檔案中,從而提供額外的除錯和跟蹤資訊。

最低階別

Serilog 實現了日誌事件處理中常見的“最低階別”概念。

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Console()
    .CreateLogger();

MinimumLevel 配置物件允許指定一個日誌事件級別作為最低階別。在上面的示例中,級別為 Debug 及更高階別的日誌事件將被處理並最終寫入控制檯。

級別

使用場景

Verbose(詳細)

詳細事件是最詳細的級別,很少(甚至從不)在生產應用程式中啟用

Debug(除錯)

除錯事件用於記錄系統內部事件,這些事件不一定能從外部觀察到,但是對應確定問題發生原因很有幫助

Information(資訊)

資訊事件描述系統中發生的事情,這些事情與系統的職責和功能相對應。通常,這些是系統可以執行的可觀察操作

Warning(警告)

當服務降級、面臨危險或可能超出其預期引數時,使用警告事件

Error(錯誤)

當功能不可用或預期被打破時,使用錯誤事件

Fatal(致命)

最關鍵的級別,致命事件需要立即關注

預設級別 - 如果未指定 MinimumLevel,則將處理 Information 級別及更高階別的事件。

覆蓋每個接收器

有時,我們希望將詳細的日誌寫入一個介質,而將不太詳細的日誌寫入另一個介質。

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.File("log.txt")
    .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Information)
    .CreateLogger();

在這個例子中,除錯級別的日誌將被寫入到滾動檔案中,而只有級別及以上的日誌會被寫入到控制檯。而只有資訊級別日誌和更高階別的日誌將寫入控制檯

所有提供的接收器都支援 restrictedToMinimumLevel 配置引數。

記錄器與接收器的最低階別 - 需要了解的是,日誌級別只能提高,而不能降低。也就是說,如果記錄器的 MinimumLevel被設定為 Information,那麼即使接收器的指定級別為 Debug,它仍然只會接收到 Information 級別的事件。這是因為記錄器級別配置是控制哪些日誌語句會導致事件的建立,而接收器級別配置是對這些事件進行篩選。如果你想要建立具有更詳細級別的單一記錄器,那麼你應該使用單獨的 LoggerConfiguration例項。

增強器

增強器是簡單的元件,用於新增、刪除或修改附加到日誌事件的屬性。例如,可以使用 增強器為每個事件附加執行緒 ID。

class ThreadIdEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty(
                "ThreadId", Thread.CurrentThread.ManagedThreadId));
    }
}

增強器是透過 Enrich 配置物件來新增的。

Log.Logger = new LoggerConfiguration()
    .Enrich.With(new ThreadIdEnricher())
    .WriteTo.Console(
        outputTemplate: "{Timestamp:HH:mm} [{Level}] ({ThreadId}) {Message}{NewLine}{Exception}")
    .CreateLogger();

上面的配置展示瞭如何透過增強器新增的屬性在輸出格式化中使用。

如果在應用程式執行期間,增強的屬性值是恆定的,可以使用快捷方法 WithProperty 來簡化配置。

Log.Logger = new LoggerConfiguration()
    .Enrich.WithProperty("Version", "1.0.0")
    .WriteTo.Console()
    .CreateLogger();

增強器以及它們附加的屬性通常與使用結構化儲存的接收器一起使用時更加有用,因為在這些接收器中可以檢視和過濾屬性值。

過濾器

事件可以透過過濾器進行選擇性記錄。過濾器只是日誌事件的篩選規則,其中一些常見場景由 Matching 類處理。

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .Filter.ByExcluding(Matching.WithProperty<int>("Count", p => p < 10))
    .CreateLogger();

子日誌記錄器

有時,需要對接收器看到的內容進行更細粒度的控制。為此,Serilog 允許完整的日誌記錄管道作為接收器使用。

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.Logger(lc => lc
        .Filter.ByIncludingOnly(...)
        .WriteTo.File("log.txt"))
    .CreateLogger();

對於子日誌記錄器處理不佳的場景,可以建立多個獨立的頂級管道。雖然 Log.Logger 只能分配一個管道,但你的應用程式可以使用任意數量的額外 ILogger 例項。

請注意,如果在 WriteTo.Logger() 回撥中指定了解構策略,則這些策略將不會生效,因為子日誌記錄器處理的是已經建立的LogEvent物件。

相關文章