从 .NET Core 3.1 (Docker) 迁移后,.NET 6 应用程序日志采用 JSON 格式

.NET 6 Application Logs are in JSON format after migration from .NET Core 3.1 (Docker)

我最近将 .NET Core REST API 从 3.1 更新到 6.0。 当我在本地 运行 应用程序而没有 Docker 在开发或发布配置中时,日志的格式一如既往:

当 运行将应用程序作为 Docker 容器时,日志将转换为 JSON。这只是在迁移到 .Net 6 之后出现的。

如何在 Docker 环境中恢复到标准日志记录格式?

更改是在 .NET 5 中进行的,而不是 6。在 .NET Core 3.1 中,控制台日志格式已修复。在 .NET 5 this is now customizable 中有 3 个预定义的格式化程序:Simple(旧的)、Systemd 和 Json(默认)。可以创建自定义格式化程序。

如文档所示,可以通过使用 AddSimpleConsole 方法而不是 AddConsole:

来使用简单格式化程序
    using ILoggerFactory loggerFactory =
        LoggerFactory.Create(builder =>
            builder.AddSimpleConsole(options =>
            {
                options.IncludeScopes = true;
                options.SingleLine = true;
                options.TimestampFormat = "hh:mm:ss ";
            }));

其他两个格式化程序也有类似的方法:AddSystemdConsoleAddJsonConsole

可以set the formatter through configuration :

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        },
        "Console": {
            "LogLevel": {
                "Default": "Information",
                "Microsoft": "Warning",
                "Microsoft.Hosting.Lifetime": "Information"
            },
            "FormatterName": "json",
            "FormatterOptions": {
                "SingleLine": true,
                "IncludeScopes": true,
                "TimestampFormat": "HH:mm:ss ",
                "UseUtcTimestamp": true,
                "JsonWriterOptions": {
                    "Indented": true
                }
            }
        }
    },
    "AllowedHosts": "*"
}

最终可以通过继承 ConsoleFormatter 并覆盖 Write 方法来创建全新的格式化程序:

public sealed class CustomFormatter : ConsoleFormatter, IDisposable
{
   ...

    public override void Write<TState>(
        in LogEntry<TState> logEntry,
        IExternalScopeProvider scopeProvider,
        TextWriter textWriter)
    {
        string? message =
            logEntry.Formatter?.Invoke(
                logEntry.State, logEntry.Exception);

        if (message is null)
        {
            return;
        }

        CustomLogicGoesHere(textWriter);
        textWriter.WriteLine(message);
    }

   ...
}