Contents

.Net Core 加上 Serillog

我們公司使用 Serillog,這邊特別去看 Serillog 怎麼使用,這邊我自學的書是教使用 Nlog,下次有機會在筆記。

安裝 Serilog.AspNetCore 流程

參考官網: Getting Started · serilog/serilog Wiki

這邊還有分console,web設定,參考網頁選單下面內容參考。

Getting started
Setting up a new console app
Setting up a new web app

這邊以 Web 專案示範,參考 serilog/serilog-aspnetcore: Serilog integration for ASP.NET Core

1
dotnet add package Serilog.AspNetCore

依賴性套件會有這些

https://i.imgur.com/X1k1xiO.png

  1. Main 方法加入下面這段
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using Serilog;
using Serilog.Events;

public class Program
{
    public static int Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
            .Enrich.FromLogContext()
            .WriteTo.Console()
            .CreateLogger();

        try
        {
            Log.Information("Starting web host");
            CreateHostBuilder(args).Build().Run();
            return 0;
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host terminated unexpectedly");
            return 1;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

這邊注意原本有CreateHostBuilder(args).Build().Run();,因為這段上面方法就有包含,所以直接把這段換成上面就好。

  1. CreateHostBuilder加入UseSerilog
1
2
3
4
5
6
7
8
    public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseSerilog() // <-- Add this line
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
}

https://i.imgur.com/PWuqIAS.png

當然設定不可能只有這樣,官方有提供一些建議。

Remove the “Logging” section from appsettings.*.json files (this can be replaced with Serilog configuration as shown in the Sample project, if required)
Remove UseApplicationInsights() (this can be replaced with the Serilog AI sink, if required)

找一些跟Application Insights相關的
Application Insights

增加日誌設定

  1. 安裝
1
Install-Package Serilog.Settings.Configuration 
  1. 設定 appsetting.json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
  "Serilog": {
    "Using":  [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
    "MinimumLevel": "Debug",
    "WriteTo": [
      { "Name": "Console" },
      { "Name": "File", "Args": { "path": "Logs/log.txt" } }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
    "Destructure": [
      { "Name": "With", "Args": { "policy": "Sample.CustomPolicy, Sample" } },
      { "Name": "ToMaximumDepth", "Args": { "maximumDestructuringDepth": 4 } },
      { "Name": "ToMaximumStringLength", "Args": { "maximumStringLength": 100 } },
      { "Name": "ToMaximumCollectionCount", "Args": { "maximumCollectionCount": 10 } }
    ],
    "Properties": {
        "Application": "Sample"
    }
  }
}

可以參考官網範例serilog/serilog-settings-configuration: A Serilog configuration provider that reads from Microsoft.Extensions.Configuration

這邊我通常不會寫那麼多

1
2
3
4
5
6
7
8
9
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    }
  },

rollOnFileSizeLimit value is not being used · Issue #184 · serilog/serilog-settings-configuration

不過我找不到 rolllog方法,最後找到rollingInterval可以做到,使用字串就能套用變數

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Information",
        "System": "Warning"
      }
    },
    "Enrich": [ "FromLogContext" ],
    "WriteTo": [
      {
        "Name": "Console"
      },
      {
        "Name": "File",
        "Args": {
          "path": "Logs/log-.txt",
          "rollingInterval": "Day",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{Method}) {Message}{NewLine}{Exception}"
        }
      }
    ]
  }

最後程式改寫如下,主要看Main方法這邊region

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
   public class Program
    {
        public static int Main(string[] args)
        {
            #region 這邊
            var configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
                .Build();

            Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(configuration)
                .CreateLogger();
#regionend 這邊
            try
            {
                Log.Information("Starting web host");
                CreateHostBuilder(args).Build().Run();

                return 0;
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "Host terminated unexpectedly");
                return 1;
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }



        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseSerilog()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

log 格式

可以參考:Formatting Output · serilog/serilog Wiki

短格式補時間

1
[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}
1
[22:59:49 INF] Request finished HTTP/1.1 GET http://localhost:5000/weatherforecast - - - 405 0 - 206.1174ms

長格式

1
{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}.{Method}) {Message}{NewLine}{Exception}
1
2
2022-07-03 23:03:35.144 +08:00 [Information] (Microsoft.AspNetCore.Hosting.Diagnostics.GET) Request finished HTTP/1.1 GET http://localhost:5000/weatherforecast - - - 405 0 - 173.3515ms
2022-07-03 23:03:38.188 +08:00 [Information] (Microsoft.Hosting.Lifetime.) Application is shutting down...

Console 標示哪知 class 錯誤

1
2
3
4
5
6
7
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
          "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}"
        }

參考官網:serilog/serilog-sinks-console: Write log events to System.Console as text or JSON, with ANSI theme support

我調整格式

1
{Timestamp:HH:mm:ss} [{Level:u3}] ({SourceContext}.{Method}) {Message}{NewLine}{Exception}

效能注意

Writing Log Events · serilog/serilog Wiki

1
2
3
readonly bool _isDebug = Log.IsEnabled(LogEventLevel.Debug);
...
if (_isDebug) Log.Debug("Someone is stuck debugging...");

log存到資料庫上

參考:Database Logging with Serilog in an ASP.NET Core Application

刪除舊檔案

參考:c# - How do I automatically tail (delete) older logs using Serilog in a .Net WPF application? - Stack Overflow

默認 31天會刪除檔案

For the same reason, only the most recent 31 files are retained by default (i.e. one long month). To change or remove this limit, pass the retainedFileCountLimit parameter.

1
    .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day, retainedFileCountLimit: null)

補上 Request Id

網路上針對加 Request Id 都是對 JSON Log 方式,仔細想想這種搜尋對 JSON 是方便的,但不是每個公司都有 ELK 工具當作 log 使用,這邊查有沒有用純 log 方式去紀錄 Request Id,所幸看到這篇ASP.NET Core Logging Solution - Run2948 - 博客园 備份圖

https://i.imgur.com/bI8ZK56.png

1
The template used for formatting plain text log output. The default is {Timestamp:o} {RequestId,13} [{Level:u3}] {Message} ({EventId:x8}){NewLine}{Exception}

只要在 OutputTemplate 補上 {RequestID} 就可以了。

要轉成 JSON 方式可以參考.NET 6.0 如何使用 Serilog 對應用程式事件進行結構化紀錄 | The Will Will Web

相關知識

預設 LevelInformation

寫格式注意的事情。

https://i.imgur.com/OjKNhZV.png

結構化處理

[NETCore] 結構化日誌 Serilog - Events Types 和 Enrichment ~ m@rcus 學習筆記

存在 SQL Server

serilog-mssql/serilog-sinks-mssqlserver: A Serilog sink that writes events to Microsoft SQL Server and Azure SQL

雖然分散式架構可以用這個集中log,但我認為這個不是最佳解。不過我們公司有再用,有空簡單嘗試。

壓縮舊 log

cocowalla/serilog-sinks-file-archive: Plugin for the Serilog File sink that works with rolling log files, archiving completed log files before they are deleted by Serilog’s retention mechanism

有空嘗試。

相關文章

【Abp VNext】实战入门(三):【3】控制台应用程序 —— Seriallog日志记录_liuyonghong159632的博客-CSDN博客_abpvnext 日志
[NETCore] 結構化日誌 Serilog - 配置設定 ~ m@rcus 學習筆記
如何在 ASP.Net Core 中使用 Serilog | IT人
將 ASP.NET Core 的預設 log 輸出至 NLog 或 Serilog - Yowko’s Notes

詳細範例

.NET 6.0 如何使用 Serilog 對應用程式事件進行結構化紀錄 | The Will Will Web
Serilog 2.10 中文文档_JimCarter的博客-CSDN博客_serilog中文文档
.net core 使用 Serilog 作为日志提供者 - IWing - 博客园
乘风破浪,遇见最佳跨平台跨终端框架.Net Core/.Net生态 - 浅析ASP.NET Core日志框架,通过Serilog来记录结构化日志 - TaylorShi - 博客园

彩蛋

Seq — centralized structured logs for . NET, Java, Node.js