Serilog Log Format Template

2024年12月30日 38点热度 1人点赞 0条评论
内容目录
Serilog:
  Using:
    - "Serilog.Sinks.Console"
  MinimumLevel:
    Default: Information
    Override:
      Microsoft.AspNetCore.HttpLogging: Information
      ProtoBuf.Grpc.Server.ServicesExtensions.CodeFirstServiceMethodProvider: Warning
      Microsoft.EntityFrameworkCore: Information
      Microsoft.AspNetCore: Warning
      System.Net.Http.HttpClient.TenantManagerClient.LogicalHandler: Warning
      Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted: Warning
      System: Information
      Microsoft: Information
      Grpc: Information
      MySqlConnector: Information
  WriteTo:
    - Name: Console
      Args:
        outputTemplate: "{SourceContext} {Scope} {Timestamp:HH:mm} [{Level}]{NewLine}    {Properties:j}{NewLine}    {Message:lj} {Exception} {NewLine}"
  Enrich:
    - FromLogContext
    - WithMachineName
    - WithThreadId

json:

{
  "Serilog": {
    "Using": [
      "Serilog.Sinks.Console"
    ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft.AspNetCore.HttpLogging": "Information",
        "ProtoBuf.Grpc.Server.ServicesExtensions.CodeFirstServiceMethodProvider": "Warning",
        "Microsoft.EntityFrameworkCore": "Information",
        "Microsoft.AspNetCore": "Warning",
        "System.Net.Http.HttpClient.TenantManagerClient.LogicalHandler": "Warning",
        "Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted": "Warning",
        "System": "Information",
        "Microsoft": "Information",
        "Grpc": "Information",
        "MySqlConnector": "Information"
      }
    },
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "{SourceContext} {Scope} {Timestamp:HH:mm} [{Level}]{NewLine}    {Properties:j}{NewLine}    {Message:lj} {Exception} {NewLine}"
        }
      }
    ],
    "Enrich": [
      "FromLogContext",
      "WithMachineName",
      "WithThreadId"
    ]
  }
}

在代码中使用,如在 ASP.NET Core 使用时:

        // Configure logging.
        builder.Logging.ClearProviders();

        builder.Host.UseSerilog((ctx, services, configuration) =>
        {
            configuration.ReadFrom.Services(services);
#if DEBUG
            // No specific formatting needed in local
            configuration.ReadFrom.Configuration(ctx.Configuration)

            // Customize the format of part of the logs
            .Enrich.With(new MyLogEnricher());
#else
            // When collecting in json, ignore log template
            ctx.Configuration["Serilog:WriteTo:0:Args:outputTemplate"] = "";

            // Output in json format
            configuration.WriteTo.Console(new RenderedCompactJsonFormatter())
            .ReadFrom.Configuration(ctx.Configuration)

            // Customize the format of part of the logs
            .Enrich.With(new MyLogEnricher());
#endif
        });

默认情况下使用 configuration.ReadFrom.Configuration(ctx.Configuration) 时,日志就是正常人类方便阅读的格式。

file

如果我们需要重定向输出,可以使用:

.WriteTo.Console(new RenderedCompactJsonFormatter())

对比:

configuration
.ReadFrom.Configuration(ctx.Configuration)
↓ ↓ ↓
configuration
.WriteTo.Console(new RenderedCompactJsonFormatter())   // 多了这一句
.ReadFrom.Configuration(ctx.Configuration)

Serilog 提供了四种 json 格式化器。

下面是四种格式化器的性能测试:

| Formatter | Median | StdDev | Scaled |
| ------------------------------------ | ---------- | --------- | ------ |
| JsonFormatter | 11.2775 µs | 0.0682 µs | 1.00 |
| CompactJsonFormatter | 6.0315 µs | 0.0429 µs | 0.53 |
| JsonFormatter(renderMessage: true) | 13.7585 µs | 0.1194 µs | 1.22 |
| RenderedCompactJsonFormatter | 7.0680 µs | 0.0605 µs | 0.63 |

建议大家使用 RenderedCompactJsonFormatter。

对于 JsonFormatter 和 CompactJsonFormatter ,只在长度上差一点,CompactJsonFormatter 的压缩性比较好,但是阅读起来不方便,这两者都是将参数模板和参数值分开存储的。

以该日志为例:

_logger.Information("Hello, {@User}, {N:x8} at {Now}", new { Name = "nblumhardt", Tags = new[] { 1, 2, 3 } }, 123, DateTime.Now);

JsonFormatter 的格式:

{
	"Timestamp": "2016-06-07T13:44:57.8532799+10:00",
	"Level": "Information",
	"MessageTemplate": "Hello, {@User}, {N:x8} at {Now}",
	"Properties": {
		"User": {
			"Name": "nblumhardt",
			"Tags": [1, 2, 3]
		},
		"N": 123,
		"Now": "2016-06-07T13:44:57.8532799+10:00"
	},
	"Renderings": {
		"N": [{
			"Format": "x8",
			"Rendering": "0000007b"
		}]
	}
}

CompactJsonFormatter 的格式:

{
	"@t": "2016-06-07T03:44:57.8532799Z",
	"@mt": "Hello, {@User}, {N:x8} at {Now}",
	"@r": ["0000007b"],
	"User": {
		"Name": "nblumhardt",
		"Tags": [1, 2, 3]
	},
	"N": 123,
	"Now": "2016-06-07T13:44:57.8532799+10:00"
}

两者都是记录日志原本的字符串 "Hello, {@User}, {N:x8} at {Now}",但是不在字符串里面重定向输出结果(格式化),而是单独使用别的属性分开存储 UserNNow 的值。

那么对于 JsonFormatter(renderMessage: true)RenderedCompactJsonFormatter 则是上面两者的重定向(格式化)版本,会直接在原字符串里面格式化。

JsonFormatter(renderMessage: true) 格式:

{
	"Timestamp": "2024-12-30T08:54:32.2909994+08:00",
	"Level": "Information",
	"MessageTemplate": "Hello, {@User}, {N:x8} at {Now}",
	"RenderedMessage": "Hello, { Name: \"nblumhardt\", Tags: [1, 2, 3] }, 0000007b at 12/30/2024 08:54:32",
	"Properties": {
		"User": {
			"Name": "nblumhardt",
			"Tags": [1, 2, 3]
		},
		"N": 123,
		"Now": "2024-12-30T08:54:32.2886810+08:00",
		"SourceContext": "BSI.SDMS.Api.Program"
	},
	"Renderings": {
		"N": [{
			"Format": "x8",
			"Rendering": "0000007b"
		}]
	}
}

RenderedCompactJsonFormatter 格式:

{
	"@t": "2024-12-30T00:53:09.8507927Z",
	"@m": "Hello, { Name: \"nblumhardt\", Tags: [1, 2, 3] }, 0000007b at 12/30/2024 08:53:09",
	"@i": "4e2159b8",
	"User": {
		"Name": "nblumhardt",
		"Tags": [1, 2, 3]
	},
	"N": 123,
	"Now": "2024-12-30T08:53:09.8484345+08:00",
	"SourceContext": "BSI.SDMS.Api.Program"
}

痴者工良

高级程序员劝退师

文章评论