最詳細 ASP.NET Core 使用 Serilog 套件寫 log 教學

之前有寫過一篇 C# 使用 Serilog 紀錄 Log (不用設定檔),但是在 ASP.NET Core 中寫法有些區別,Serilog 官方的範例也有點過時,在做了一些研究,整理後寫了這篇,希望能夠幫助到需要的人。

測試環境:
Windows 11
Rider 2022.2.3
.NET SDK 6.0.401
Serilog.AspNetCore 6.0.1
在開始前需要先使用 NuGet 安裝 Serilog.AspNetCore ,需要 .NET Core 3 或以上
    
dotnet add package Serilog.AspNetCore
    

啟動時直接使用 Serilog

本文示範是使用 Web Api 專案,在剛開啟新專案時 Program.cs 長的樣子:
    
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
    

替換為:
    
using Serilog;
using Serilog.Events;

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .WriteTo.File("logs/log-.log",
        rollingInterval: RollingInterval.Hour, // 每小時一個檔案
        retainedFileCountLimit: 24 * 30 // 最多保留 30 天份的 Log 檔案
    )
    .CreateLogger();

var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Log.CloseAndFlush();
    

更好的做法就是使用 把上面 15 到 40 行的部分用 try catch 包起來,因為後面程式越寫越多,在初始化時可能會發生錯誤,包這層 try catch 就可以直接捕捉到例外狀況
    
try
{
	// 裡面放上面的 15 至 40 行
}
catch (Exception e)
{
    Log.Error(e, "Host terminated unexpectedly");
}

Log.CloseAndFlush();
    

因為我們使用 Serilog 寫 Log,所以就可以把 appsettings.json 裡面一開始產生的 Logging 區塊移除 (2 到 7 行)
    
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}
    

兩階段初始化

在官方 Serilog.AspNetCore 的 Github 頁面也有說明到在上面的方式中來自 ASP.NET Core 主機的服務、依賴注入和 Log 外部設定檔都無法使用,所以最好要加上第二階段的初始化

將第 10 行刪掉,換成第 11 行的 CreateBootstrapLogger
    
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .WriteTo.File("logs/log-.log",
        rollingInterval: RollingInterval.Hour, // 每小時一個檔案
        retainedFileCountLimit: 24 * 30 // 最多保留 30 天份的 Log 檔案
    )
    // .CreateLogger();
    .CreateBootstrapLogger();

    

再將下面的第 2 行刪掉,換成 3 至 10 行,會要這麼麻煩把 WriteTo 的內容再寫一次是因為第一階段的 Log 轉移給第二階段之後就會被完全替換掉,變成新的。所以如果沒有再寫一次的話就會什麼都不輸出...
    
    var builder = WebApplication.CreateBuilder(args);
    // builder.Host.UseSerilog();
    builder.Host.UseSerilog((context, services, configuration) => configuration
        .ReadFrom.Services(services)
        .Enrich.FromLogContext()
        .WriteTo.Console()
        .WriteTo.File("logs/log-.log",
            rollingInterval: RollingInterval.Hour, // 每小時一個檔案
            retainedFileCountLimit: 24 * 30 // 最多保留 30 天份的 Log 檔案
        )
    );
    

使用設定檔

剛剛有提到從第二階段開始才可以使用設定檔,於是順便紀錄一下設定檔的使用方式和內容

增加第 3 行,刪除 6-10 行
    
    var builder = WebApplication.CreateBuilder(args);
    builder.Host.UseSerilog((context, services, configuration) => configuration
        .ReadFrom.Configuration(context.Configuration) // 從設定檔中讀取
        .ReadFrom.Services(services)
        .Enrich.FromLogContext()
        // .WriteTo.Console()
        // .WriteTo.File("logs/log-.log",
        //     rollingInterval: RollingInterval.Hour, // 每小時一個檔案
        //     retainedFileCountLimit: 24 * 30 // 最多保留 30 天份的 Log 檔案
        // )
    );
    

將設定檔(appsettings.json) 新增以下內容,這些設定值等同於本文最一開始寫在 C# 的 Log 設定內容
    
{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft.AspNetCore": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "Console"
      },
      {
        "Name": "File",
        "Args": {
          "path": "logs/log-.log",
          "rollingInterval": "Hour",
          "retainedFileCountLimit": 720
        }
      }
    ]
  },
  "AllowedHosts": "*"
}

    


延伸閱讀:
ASP.NET Core 實際輸出日誌訊息

參考資料:
Serilog
Serilog.AspNetCore
Serilog.Settings.Configuration

留言