当前位置: 首页 > 科技观察

在ASP.NETCore中使用Serilog-Fluentd将日志写入Elasticsearch

时间:2023-03-20 18:21:37 科技观察

转载请联系DotNET技术圈公众号。原文来自:https://andrewlock.net/writing-logs-to-elasticsearch-with-fluentd-using-serilog-in-asp-net-core/对于在Kubernetes中运行的应用程序,将日志消息存储在Central位置是特别重要。我认为这对所有应用程序都很重要,无论您使用的是Kubernetes还是docker,但pod和容器的短暂性质使得后一种情况尤为重要。如果不将日志集中存储在容器中,那么如果容器崩溃并重启,日志可能会永远丢失。有很多方法可以实现这一点。您可以直接从您的应用程序登录Elasticsearch或Seq,或登录Elmah.io等外部服务。一种常见的方法是使用Fluentd从容器的控制台输出中收集日志,并将这些日志通过管道传输到Elasticsearch集群。默认情况下,ASP.NETCore中的控制台日志输出格式为人类可读的格式。如果您采用Fluentd/Elasticsearch方法,则需要确保您的控制台输出采用Elasticsearch可以理解的结构化格式,即JSON。在本文中,我描述了如何将Serilog添加到ASP.NETCore应用程序,以及如何自定义Serilog控制台接收器的输出格式,以便您可以使用Fluentd将控制台输出通过管道传输到Elasticsearch。请注意,Serilog也可以配置为使用Elasticsearch接收器直接写入Elasticsearch。如果您不使用Fluentd或容器化您的应用程序,这是一个不错的选择。将日志写入控制台输出当您从模板创建新的ASP.NETCore应用程序时,您的程序文件将如下所示(至少在.NETCore2.1中):.Build().Run();}publicstaticIWebHostBuilderCreateWebHostBuilder(string[]args)=>WebHost.CreateDefaultBuilder(args).UseStartup();}静态辅助方法WebHost.CreateDefaultBuilder(args)创建一个WebHostBuilder并连接多个标准配置选项[1]。默认情况下,它配置控制台和调试记录器提供程序:.ConfigureLogging((hostingContext,logging)=>{logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));logging.AddConsole();logging.AddDebug();})如果您使用dotnetrun从命令行运行您的应用程序,您将在控制台中看到每个请求的日志。浏览器的两个请求生成的日志如下所示-一个用于主页,一个用于favicon.ico。使用默认控制台记录器的控制台输出不幸的是,控制台记录器在日志的写入方式上没有提供很大的灵活性。您可以选择包括范围或禁用颜色,仅此而已。ASP.NETCore中默认Microsoft.Extensions.Logging基础结构的替代方法是使用Serilog进行日志记录并将其连接为标准ASP.NETCore记录器。将Serilog添加到ASP.NETCore应用程序Serilog是一个成熟的开源项目,早于ASP.NETCore中的所有日志记录基础结构。在许多方面,ASP.NETCore日志记录基础结构似乎是在Serilog之后建模的:Serilog具有类似的配置选项和可插入的“接收器”来控制日志的写入位置。开始使用Serilog的最简单方法是使用Serilog.AspNetCoreNuGet包。通过以下方式将其添加到您的应用程序:dotnetaddpackageSerilog.AspNetCore您还需要添加一个或多个“接收器”包来控制日志的写入位置。在这种情况下,我将安装控制台接收器,但如果您想同时写入多个目的地,您可以添加其他接收器。dotnetaddpackageSerilog.Sinks.ConsoleSerilog.AspNetCore包UseSerilog()在WebHostBuilder实例上提供了一个扩展方法。这将默认值替换为ILoggerFactorySerilog的实现。您可以传入现有的Serilog.ILogger实例,或配置内联记录器。例如,以下代码配置将写入的最低日志级别(info)并注册控制台接收器:publicstaticIWebHostBuilderCreateWebHostBuilder(string[]args)=>WebHost.CreateDefaultBuilder(args).UseSerilog((ctx,config)=>{config.MinimumLevel.Information().Enrich.FromLogContext().WriteTo.Console();}).UseStartup();}当您使用Serilog而不是默认记录器时再次运行应用程序会提供以下控制台输出:使用Serilog代替默认的控制台记录器控制台输出输出类似于默认记录器,但重要的是它是非常可配置的。您可以根据需要更改输出模板。例如,您可以通过包含SourceContext参数来显示生成日志的类的名称。有关Serilog.AspNetCore包的更多详细信息和示例可以在GitHub存储库[2]中找到。有关控制台格式选项,请参阅Serilog.Sinks.Console存储库[3]。除了对输出模板进行简单更改外,控制台接收器还允许完全控制消息的呈现方式。我们将使用此功能将日志呈现为Fluentd的JSON,而不是人性化的格式。自定义SerilogConsoleSink的输出格式以写入JSON要更改数据的呈现方式,您可以添加自定义ITextFormatter。Serilog包含一个您可以使用的JsonFormatter,但建议您考虑使用Serilog.Formatting.Compact包[4]:“与Serilog的默认JsonFormatter相比,CompactJsonFormatter大大减少了小型日志事件的字节数,同时保持人类可读性。它通过更短的内置属性名称、更紧凑的格式和排除冗余信息来实现这一点。“我们不会将这个包用于我们的Fluentd/Elasticsearch用例,但我将展示如何将它插入任何案件。使用添加包dotnet添加包Serilog.Formatting.Compact,创建格式化程序的新实例并将其传递给调用UseSerilog()时的WriteTo.Console()方法:.UseSerilog((ctx,config)=>{config.MinimumLevel.Information().Enrich.FromLogContext().WriteTo.Console(newCompactJsonFormatter());})现在,如果你运行你的应用程序,你将看到以JSON格式写入控制台的日志:JSON格式的控制台此格式化程序可能适合您,但就我而言,我想编写JSON以便Elasticsearch可以理解它。您可以看到紧凑的JSON格式(下面打印得很漂亮),正如所承诺的那样,使用紧凑的时间戳名称(@t)、消息模板(@mt)和呈现的消息(@r):{"@t":"2018-05-17T10:23:47.0727764Z","@mt":"{HostingRequestStartingLog:l}","@r":["RequeststartingHTTP\/1.1GEThttp:\/\/localhost:5000\/"],"协议":"HTTP\/1.1","方法":"GET","ContentType":null,"ContentLength":null,"Scheme":"http","Host":"localhost:5000","PathBase":"","Path":"\/","QueryString":"","HostingRequestStartingLog":"RequeststartingHTTP\/1.1GEThttp:\/\/localhost:5000\/","EventId":{"Id":1},"SourceContext":"Microsoft.AspNetCore.Hosting.Internal.WebHost","RequestId":"0HLDRS135F8A6:00000001","RequestPath":"\/","CorrelationId":null,"ConnectionId":"0HLDRS135F8A6"}对于最简单的Fluentd/Elasticsearch集成,我想使用标准的Elasticsearch名称(例如@timestamptimestamp)输出JSON幸运的是,所需要的只是更改格式化程序。使用与Elasticsearch兼容的JSON格式化程序TheSerilog.Sinks.Elasticsearch包中正好包含了我们需要的格式ElasticsearchJsonFormatter。这个使用标准的Elasticsearch字段(如@timestamp和)来渲染数据字段。不幸的是,目前除了复制粘贴源代码外没有其他方法先检查许可证此外,将格式化程序添加到您的项目的唯一方法是安装整个Serilog.Sinks.Elasticsearch包,它有很多依赖项。理想情况下,我希望将格式化程序视为它自己的独立包,就像Serilog一样。Formatting.CompaconeImadeanissue[5]如果这对你来说不是问题(这对我来说不是问题,因为我已经依赖Elasticsearch.Net,然后添加ElasticsearchSink来访问格式化程序是最简单的解决方案。使用dotnet添加包Serilog.Sinks.ElasticSearch添加接收器,并更新您的Serilog配置以使用ElasticsearchJsonFormatter:.UseSerilog((ctx,config)=>{config.MinimumLevel.Information().Enrich.FromLogContext().WriteTo.Console(newElasticsearchJsonFormatter();})连接此格式化程序后,控制台输出将包含常见的Elasticsearch字段,例如@timestamp,如以下(漂亮打印)输出所示:{"@timestamp":"2018-05-17T22:31:43.9143984+12:00","level":"信息","messageTemplate":"{HostingRequestStartingLog:l}","message":"RequeststartingHTTP\/1.1GEThttp:\/\/localhost:5000\/",“字段”:{“协议”:“HTTP\/1.1”,“方法”:“GET”,“ContentType”:null,“ContentLength”:null,“方案”:“http”,“主机”:“localhost:5000","PathBase":"","Path":"\/","QueryString":"","HostingRequestStartingLog":"请求ststartingHTTP\/1.1GEThttp:\/\/localhost:5000\/","EventId":{"Id":1},"SourceContext":"Microsoft.AspNetCore.Hosting.Internal.WebHost","RequestId":"0HLDRS5H8TSM4:00000001","RequestPath":"\/","CorrelationId":null,"ConnectionId":"0HLDRS5H8TSM4"},"呈现":{"HostingRequestStartingLog":[{"格式":"l","呈现":"RequeststartingHTTP\/1.1GEThttp:\/\/localhost:5000\/"}]}}现在日志以一种可以直接从Fluentd流式传输到Elasticsearch的格式呈现,我们可以只写入控制台。取决于在Switchingbetweenoutputformatters中的托管环境最后提示。如果在本地开发时想要人类可读的控制台输出,并且只在暂存或生产中使用JSON格式化程序怎么办?由于UseSerilog扩展,这很容易做到提供了IHostingEnvironment通过WebHostBuilderContext。例如,在下面的代码片段中,我将应用程序配置为在开发中使用人类可读的控制台,在其他环境中使用JSON格式化程序..UseSerilog((ctx,config)=>{config.MinimumLevel.Information().Enrich.FromLogContext();if(ctx.HostingEnvironment.IsDevelopment()){config.WriteTo.Console();}else{config.WriteTo.Console(newElasticsearchJsonFormatter());}})除了环境,你还可以根据ctx.Configuration中通过IConfiguration对象提供的配置值进行切换。简而言之,将日志存储在一个中央位置很重要,尤其是在构建容器化应用程序时。一种可能的解决方案是登录到控制台,让Fluentd监控控制台,并将输出通过管道传输到Elasticsearch集群。在本文中,我描述了如何将Serilog日志记录添加到您的ASP.NETCore应用程序并将其配置为以Elasticsearch期望的JSON格式将日志写入控制台。参考文献[1]链接了许多标准配置选项:https://github.com/aspnet/MetaPackages/blob/2.1.0-rc1-final/src/Microsoft.AspNetCore/WebHost.cs#L150[2]请参阅GitHub存储库:https://github.com/serilog/serilog-aspnetcore[3]Serilog.Sinks.Console存储库:https://github.com/serilog/serilog-sinks-console[4]考虑使用Serilog.Formatting。压缩包:https://github.com/serilog/serilog-formatting-compact[5]我提出了一个问题:https://github.com/serilog/serilog-sinks-elasticsearch/issues/176