【问题标题】:How To Get Log Level in Json with Serilog - .NET Core 3.1如何使用 Serilog 在 Json 中获取日志级别 - .NET Core 3.1
【发布时间】:2020-02-04 14:49:02
【问题描述】:

我是Serilog 的新手,我正在尝试确定如何使用log leveldate time 字段将序列化的json 发送到consolestructured data 下的文档中似乎没有任何信息。

这是我在Startup.cs 中调用的代码:

private void LoggerLoop(ILogger<Startup> logger)
{
    RabbitModel rb = new RabbitModel
    {
        Id = 1,
        DeviceNum = 1,
        DeviceName = "Device 1",
        InputNum = 1,
        InputName = "Input 1",
        InputState = 1,
        OnPhrase = "On",
        OffPhrase = "Off",
        When = "2020-01-01T22:45:00.1124303+00:00"
    };

    while (true)
    {
        logger.LogInformation("{@rb}", rb);
        Thread.Sleep(1000);
    }
}

这是我的输出:

[14:28:22 INF] {"Id": 1, "DeviceNum": 1, "DeviceName": "Device 1", "InputNum": 1, "InputName": "Input 1", "InputState": 1, "OnPhrase": "On", "OffPhrase": "Off", "When": "2020-01-01T22:45:00.1124303+00:00", "$type": "RabbitModel"}

我确实注意到它添加了一个字段 $type 并想知道是否可以将 [14:28:22 INF] 添加到 json 中?

【问题讨论】:

  • 为什么需要 json 格式的数据?
  • 我特别想要 json 中的日志级别和其余部分,因为我不想将它与 Elasticsearch 一起使用
  • 为此使用Elasticsearch sink。它会自动将所有日志数据转换为 json(弹性格式)。您可以直接写入弹性文件,或使用ElasticsearchJsonFormatter 写入控制台,但是您需要一些可以收集日志并将其发送到弹性文件的东西。用容器就可以流利了
  • 谢谢,是的,我正在从容器中运行一切。我计划通过 Docker 容器将 json 发送到 Filebeat,然后将这些数据发送到 Elasticsearch。
  • 我将描述我们的流程:根据12 factor app所有日志以elasticsearch格式写入stdout(控制台),然后我们有安装了fluentd的kubernetes集群,它从容器中收集所有日志(通过过滤器)并将其发送到 Elastic。所有日志都是structured,它改进了在 Kibana 中的搜索

标签: c# elasticsearch asp.net-core serilog


【解决方案1】:

根据12 factor app,应用程序应该将所有日志写入stdout/stderr

然后您需要将所有日志收集在一起,并路由到一个或多个最终目的地以供查看 (Elasticserach)。开源日志路由器(如FluentBitFluentdLogplex)可用于此目的。

因此,应用从不关心其日志的路由或存储。在 dotnet app 中使用Serilog可以轻松实现

假设我们在 appsettings.json

中有以下记录器设置
"Logging": {
    "OutputFormat": "console",
    "MinimumLevel": "Information"
}

我们可以创建一个扩展方法

private static IWebHostBuilder CreateWebHostBuilder() =>
    WebHost.CreateDefaultBuilder()
        .UseStartup<Startup>()
        .UseLogging();
}

可以以纯文本和弹性搜索格式将日志写入控制台。纯文本日志对开发很有用,因为它更易于阅读。在生产环境中,我们启用了 elasticsearch 格式并仅在 Kibana 中查看所有日志。

cmets扩展代码:

public static IWebHostBuilder UseLogging(this IWebHostBuilder webHostBuilder, string applicationName = null) =>
    webHostBuilder
        .UseSetting("suppressStatusMessages", "True") // disable startup logs
        .UseSerilog((context, loggerConfiguration) =>
        {
            var logLevel = context.Configuration.GetValue<string>("Logging:MinimumLevel"); // read level from appsettings.json
            if (!Enum.TryParse<LogEventLevel>(logLevel, true, out var level))
            {
                level = LogEventLevel.Information; // or set default value
            }

            // get application name from appsettings.json
            applicationName = string.IsNullOrWhiteSpace(applicationName) ? context.Configuration.GetValue<string>("App:Name") : applicationName;

            loggerConfiguration.Enrich
                .FromLogContext()
                .MinimumLevel.Is(level)
                .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                .MinimumLevel.Override("System", LogEventLevel.Warning)
                .Enrich.WithProperty("Environment", context.HostingEnvironment.EnvironmentName)
                .Enrich.WithProperty("ApplicationName", applicationName);

            // read other Serilog configuration
            loggerConfiguration.ReadFrom.Configuration(context.Configuration);

            // get output format from appsettings.json. 
            var outputFormat = context.Configuration.GetValue<string>("Logging:OutputFormat");
            switch (outputFormat)
            {
                case "elasticsearch":
                    loggerConfiguration.WriteTo.Console(new ElasticsearchJsonFormatter());
                    break;
                default:
                    loggerConfiguration.WriteTo.Console(
                        theme: AnsiConsoleTheme.Code,
                        outputTemplate: "[{Timestamp:yy-MM-dd HH:mm:ss.sssZ} {Level:u3}] {Message:lj} <s:{Environment}{Application}/{SourceContext}>{NewLine}{Exception}");
                    break;
            }
        });

OutputFormatelasticsearch 时,日志会是这样的

{"@timestamp":"2020-02-07T16:02:03.4329033+02:00","level":"信息","messageTemplate":"获取 客户 ID:{CustomerId}","message":"通过 ID 获取客户: 20","字段":{"CustomerId":20,"SourceContext":"Customers.Api.Controllers.CustomerController","ActionId":"c9d77549-bb25-4f87-8ea8-576dc6aa1c57","ActionName":"客户.Api.Controllers.CustomerController.Get (Customers.Api)","RequestId":"0HLTBQP5CQHLM:00000004","RequestPath":"/v1/customers","CorrelationId":"daef8849b662117e","ConnectionId":"0HLTBQP5CQHLM","Environment":"开发","ApplicationName":"API","Timestamp":"2020-02-07T14:02:03.4329033Z"}}

在其他情况下(仅用于调试)

[20-02-07 13:59:16.16Z INF] 通过 id 获取客户:20

然后您应该配置日志路由器以从容器中收集日志并将其发送到 Elasticsearch。

如果所有日志都是structured,它会改进 Kibana 中的搜索和创建索引。

【讨论】:

  • 谢谢,你不知道appsettings.json 等同于ElasticsearchJsonFormatter() 吗?目前我有"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog"。我已经在 nuget 中安装了Serilog.formatting.elasticsearch
  • 什么意思?是的,你需要安装包Serilog.Formatting.Elasticsearch
  • 我刚刚在他们的 github 上发布了这个:github.com/serilog/serilog-sinks-elasticsearch/issues/314。我正在从 appsettings.json 配置 Serilog,而不是在代码中更新 ElasticsearchJsonFormatter()。这会是什么?
  • 我在这一行遇到错误applicationName = string.IsNullOrWhiteSpace(applicationName) ? context.Configuration.GetValue&lt;string&gt;("App:Name") : applicationName;
  • 如果您不需要,只需删除此行。查看更新的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多