Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何从Serilog请求日志记录中排除健康检查终结点

如何从Serilog请求日志记录中排除健康检查终结点

作者头像
依乐祝
发布于 2020-02-17 06:54:16
发布于 2020-02-17 06:54:16
1.5K00
代码可运行
举报
文章被收录于专栏:依乐祝依乐祝
运行总次数:0
代码可运行

这是在ASP.NET Core 3.X中使用Serilog.AspNetCore系列文章的第四篇文章:。

  1. 第1部分-使用Serilog RequestLogging减少日志详细程度
  2. 第2部分-使用Serilog记录所选的终结点属性
  3. 第3部分-使用Serilog.AspNetCore记录MVC属性
  4. 第4部分-从Serilog请求日志记录中排除健康检查端点(本文)

作者:依乐祝 译文地址:https://cloud.tencent.com/developer/article/1584727 原文地址:https://andrewlock.net/using-serilog-aspnetcore-in-asp-net-core-3-excluding-health-check-endpoints-from-serilog-request-logging/

在本系列的前几篇文章中,我描述了如何配置Serilog的RequestLogging中间件以向Serilog的请求日志摘要中添加附加属性,例如请求主机名或选定的端点名称。我还展示了如何使用过滤器将MVC或RazorPage特定的属性添加到摘要日志。

在本文中,我将展示如何过滤掉某个特定请求的摘要日志消息。当您有一个访问比较频繁的端点时,这非常有用,因为为每个请求都进行记录几乎没有什么价值。

健康检查访问较频繁

这篇文章的动机来自我们在Kubernetes中运行应用程序时看到的行为。Kubernetes使用两种类型的“健康检查”(或“探针”)来检查应用程序是否正常运行:liveness probes和readiness probes。您可以将探测配置为向应用程序发出HTTP请求,作为应用程序正常运行的指示器。

从Kubernetes 1.16版开始,存在第三种探针,即startup probe

在ASP.NET Core 2.2+中提供的健康检查终结点非常适合这些探针。您可以设置一个简单,没有任何返回值的健康检查,该健康检查对每个请求返回200 OK的响应,以使Kubernetes知道您的应用程序没有崩溃。

在ASP.NET Core 3.x中,可以使用终结点路由来配置健康检查。您必须在Startup.cs中ConfigureServices中通过调用AddHealthChecks()来添加必须的服务,并在Configure中使用MapHealthChecks()来添加健康检查终结点:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // ..other service configuration

        services.AddHealthChecks(); // Add health check services
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            // .. other middleware
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHealthChecks("/health"); //Add health check endpoint
                endpoints.MapControllers();
            });
        }
}

在上面的示例中,向/healthz发送请求将调用健康检查终结点。由于我没有配置任何运行状况检查200,因此只要应用程序正在运行,端点将始终返回响应:

在上面的示例中,向/healthz发送请求将调用运行状况检查终结点。由于我没有配置任何运行的健康检查,因此只要应用程序正在运行,端点将始终返回200响应:

这里存在的唯一的问题是Kubernetes将非常频繁的调用这个终结点。当然,确切的频率由您决定,但每10秒检查一次应该是很常见的。但是如果你想让Kubernetes可以快速重启有故障的Pod的话,您就需要一个相对较高的频率了。

这本身不是问题;Kestrel每秒可以处理数百万个请求,因此这不是性能问题。这里令人比较烦恼的问题是每个请求都会生成一定数量的日志。虽然它没有MVC基础架构的请求所示的那么多-每个请求10个日志,但是即使每个请求只有1个日志(就像我们从Serilog.AspNetCore获得的那样)都可能会令人不快。

这里的主要问题是成功进行健康检查请求的日志实际上并未告诉我们任何有用的信息。它们与任何业务活动都不相关,它们纯粹是基础设施。这里如果能够跳过这些请求的Serilog请求摘要日志会很好。在下一部分中,我将介绍我所想出的方法,该方法依赖于本系列前面几篇文章的内容,并在其基础上做出更改。

定制用于Serilog请求日志的日志级别

上一篇文章中,我展示了如何在Serilog请求日志中包括所选终结点。我的方法是在注册Serilog中间件时为RequestLoggingOptions.EnrichDiagnosticContext属性提供一个自定义函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... Other middleware

    app.UseSerilogRequestLogging(opts
        // EnrichFromRequest helper function is shown in the previous post
        => opts.EnrichDiagnosticContext = LogHelper.EnrichFromRequest); 

    app.UseRouting();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHealthChecks("/healthz"); //Add health check endpoint
        endpoints.MapControllers();
    });
}

RequestLoggingOptions具有另一个属性,GetLevel该属性的Func<>被用于确定应用于给定请求日志的日志记录级别。默认情况下,它设置为以下功能

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static class SerilogApplicationBuilderExtensions
{
    static LogEventLevel DefaultGetLevel(HttpContext ctx, double _, Exception ex) =>
        ex != null
            ? LogEventLevel.Error 
            : ctx.Response.StatusCode > 499 
                ? LogEventLevel.Error 
                : LogEventLevel.Information;
}

此函数检查是否为请求引发了异常,或者响应代码是否为5xx错误。如果是这样,它将创建一个Error级别的摘要日志,否则将创建一个Information级别日志。

假设您希望将摘要日志记录为Debug而不是Information。首先,您将创建一个具有以下所需逻辑的辅助函数,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static class LogHelper
{
    public static LogEventLevel CustomGetLevel(HttpContext ctx, double _, Exception ex) =>
        ex != null
            ? LogEventLevel.Error 
            : ctx.Response.StatusCode > 499 
                ? LogEventLevel.Error 
                : LogEventLevel.Debug; //Debug instead of Information
}

然后,您可以在调用时设置级别功能UseSerilogRequestLogging()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... Other middleware

    app.UseSerilogRequestLogging(opts => {
        opts.EnrichDiagnosticContext = LogHelper.EnrichFromRequest;
        opts.GetLevel = LogHelper.CustomGetLevel; // Use custom level function
    });

    //... other middleware
}

现在,您的请求摘要日志将全部记录为Debug,除非发生错误(Seq的屏幕截图):

但这如何解决我们的冗长日志的问题呢?

当你在配置Serilog时,你通常应该会定义一个最低请求级别。例如,以下简单配置将默认级别设置为Debug(),并将其写入控制台接收器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Console()
    .CreateLogger();

因此,过滤日志的最简单方法是使日志级别低于MinimumLevel记录器配置中指定的级别。一般而言,如果使用最低级别Verbose,它将几乎总是被过滤掉。

困难之处在于我们不想总是Verbose用作摘要日志的日志级别。如果这样做,我们将不会获得任何非错误的请求日志,而Serilog中间件将变得毫无意义!

相反,我们希望将日志级别设置为Verbose 针对运行健康检查端点的请求。在下一节中,我将展示如何在不影响其他请求的情况下识别这些请求。

将自定义日志级别用于健康检查终结点请求

我们需要的是能够在写入摘要日志时识别出健康检查的请求的能力。如前所示,该GetLevel()方法将当前HttpContext作为参数,因此理论上有一些可行性。对我来说,最明显的做法是:

  • HttpContext.Request路径与已知的健康检查路径列表进行比较
  • 当健康检查终结点被请求时,使用选定的端点元数据来进行标识

第一种选择是最明显的,但是它真的不值得尝试。一旦你陷入其中,你会发现你必须开始复制请求路径并处理各种边缘情况,因此在这里我将跳过该情况。

第二种方法使用了与我上一篇文章中使用的方法类似,在该方法中,我们获得了EndpointRoutingMiddleware为给定请求选择的IEndpointFeature。此功能(如果存在)提供了所选端点的显示名称和路由数据等详细信息。

如果我们假设健康检查是使用默认显示名称注册的,即"Health checks",则我们可以使用HttpContext来标识“健康检查”的请求,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static class LogHelper
{
    private static bool IsHealthCheckEndpoint(HttpContext ctx)
    {
        var endpoint = ctx.GetEndpoint();
        if (endpoint is object) // same as !(endpoint is null)
        {
            return string.Equals(
                endpoint.DisplayName, 
                "Health checks",
                StringComparison.Ordinal);
        }
        // No endpoint, so not a health check endpoint
        return false;
    }
}

我们可以将此功能与默认GetLevel功能的自定义版本结合使用,以确保运行健康检查请求的摘要日志使用Verbose级别,当发生错误时使用Error而其他请求则使用Information

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static class LogHelper
{
    public static LogEventLevel ExcludeHealthChecks(HttpContext ctx, double _, Exception ex) => 
        ex != null
            ? LogEventLevel.Error 
            : ctx.Response.StatusCode > 499 
                ? LogEventLevel.Error 
                : IsHealthCheckEndpoint(ctx) // Not an error, check if it was a health check
                    ? LogEventLevel.Verbose // Was a health check, use Verbose
                    : LogEventLevel.Information;
        }
}

这个嵌套的三目运算符有一个额外的逻辑-对于无错误,我们检查是否选择了显示名为“Health check”的端点,如果选择了,则使用级别Verbose,否则使用Information

您可以进一步推广此代码,以允许传入其他显示名称或其他自定义使用的日志级别。为了简单起见,我在这里没有这样做,但是GitHub上的相关示例代码显示了如何执行此操作

剩下的就是更新Serilog中间件RequestLoggingOptions以使用您的新功能:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... Other middleware

    app.UseSerilogRequestLogging(opts => {
        opts.EnrichDiagnosticContext = LogHelper.EnrichFromRequest;
        opts.GetLevel = LogHelper.ExcludeHealthChecks; // Use the custom level
    });

    //... other middleware
}

这时候当你运行应用程序后检查日志时,您会看到标准请求的普通请求日志,但没有健康检查的日志(除非发生错误!)。在下面的屏幕截图中,我将Serilog配置为也记录Verbose日志,以便您可以查看运行状况检查请求-通常会将它们过滤掉!

总结

在本文中,我展示了如何为Serilog中间件的RequestLoggingOptions提供一个自定义函数,该函数定义了要为给定请求的日志使用的LogEventLevel。例如,我展示了如何使用它将默认级别更改为Debug。如果您选择的级别低于最低级别,它将被完全过滤掉,并且不会被记录。

我还展示了您可以使用这种方法来过滤通过调用健康检查端点生成的公共(低级别的)请求日志。一般来说,这些请求只有在指出问题时才有意义,但它们通常也会在成功时生成请求日志。由于这些端点被频繁调用,因此它们可以显著增加写入的日志数量(无用)。

本文中的方法是检查选定的IEndpointFeature并检查它是否具有显示名称“Health checks”。如果是,请求日志将使用Verbose级别写入,这通常会被过滤掉。为了更灵活,您可以自定义在这个帖子中显示的日志来处理多个端点名称,或者任何其他的标准。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-02-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Serilog高级玩法之用Serilog记录所选终结点附加属性
这是该系列的第二篇文章:在ASP.NET Core 3.0中使用Serilog.AspNetCore。
依乐祝
2020/02/14
1.9K0
Serilog高级玩法之用Serilog记录所选终结点附加属性
如何利用Serilog的RequestLogging来精简ASP.NET Core的日志输出
这是该系列的第一篇文章:在ASP.NET Core 3.0中使用Serilog.AspNetCore。
依乐祝
2020/02/14
1.8K0
如何利用Serilog的RequestLogging来精简ASP.NET Core的日志输出
.Net Core实现健康检查
ASP.NET Core 提供运行状况检查中间件和库,以用于报告应用基础结构组件的运行状况。 运行状况检查由应用程序作为 HTTP 终结点公开。可以为各种实时监视方案配置运行状况检查终结点:
梁规晓
2019/11/07
1.2K0
.Net Core实现健康检查
.Net Core实现健康检查
ASP.NET Core 提供运行状况检查中间件和库,以用于报告应用基础结构组件的运行状况。
HueiFeng
2020/01/22
7550
在.NET Core 中实现健康检查
.NET Core中提供了开箱即用的运行状况检查,首先,我将在.NET Core API应用程序中执行运行状况检查,接下来,我们将使用DbContext集成SQL Server或数据库的运行状况检查,最后是如何实现自定义服务的运行状况检查。
全球技术精选
2021/02/19
9520
在.NET Core 中实现健康检查
ASP.NET Core端点路由 作用原理
端点路由(Endpoint Routing)最早出现在ASP.NET Core2.2,在ASP.NET Core3.0提升为一等公民。
有态度的马甲
2020/07/14
1.2K0
ASP.NET Core端点路由 作用原理
理解ASP.NET Core - 路由(Routing)
链接:cnblogs.com/xiaoxiaotank/p/15468491.html
郑子铭
2022/03/22
1.8K0
理解ASP.NET Core - 路由(Routing)
将终结点图添加到你的ASP.NET Core应用程序中
在本文中,我将展示如何使用DfaGraphWriter服务在ASP.NET Core 3.0应用程序中可视化你的终结点路由。上面文章我向您演示了如何生成一个有向图(如我上篇文章中所示),可以使用GraphVizOnline将其可视化。最后,我描述了应用程序生命周期中可以检索图形数据的点。
依乐祝
2020/07/21
3.9K0
Asp.Net Core EndPoint 终结点路由工作原理解读
在本打算写一篇关于Identityserver4 的文章时候,却发现自己对EndPoint -终结点路由还不是很了解,故暂时先放弃了IdentityServer4 的研究和编写;所以才产生了今天这篇关于EndPoint (终结点路由) 的文章。
Jlion
2022/04/07
1K0
Asp.Net Core EndPoint 终结点路由工作原理解读
如何使用Serilog.AspNetCore记录ASP.NET Core3.0的MVC属性
在我上篇文章中,我描述了如何配置Serilog的RequestLogging中间件以向Serilog的请求日志摘要中添加其他属性(例如请求主机名或选定的端点名称)。这些属性都在HttpContext中可用,因此可以由中间件本身直接添加。
依乐祝
2020/02/14
3.8K0
如何使用Serilog.AspNetCore记录ASP.NET Core3.0的MVC属性
.Net Core 路由处理
  用户请求接口路由,应用返回处理结果。应用中如何匹配请求的数据呢?为何能如此精确的找到对应的处理方法?今天就谈谈这个路由。路由负责匹配传入的HTTP请求,将这些请求发送到可以执行的终结点。终结点在应用中进行定义并且在应用启动的时候进行配置,也就是在中间件中进行处理。
小世界的野孩子
2021/04/13
7710
Java一分钟之-Spring Boot Actuator:健康检查与监控
Spring Boot Actuator 是Spring Boot应用监控和管理的强大工具集,它提供了丰富的端点(Endpoints)用于健康检查、性能监控及应用配置信息查看等。本文旨在深入浅出地介绍Actuator的使用、常见问题、易错点及其规避策略,并附上实用的代码示例。
Jimaks
2024/06/08
2.6K0
【5min+】保持程序健康的秘诀!AspNetCore的HealthCheck
【五分钟的dotnet】是一个利用您的碎片化时间来学习和丰富.net知识的博文系列。它所包含了.net体系中可能会涉及到的方方面面,比如C#的小细节,AspnetCore,微服务中的.net知识等等。 5min+不是超过5分钟的意思,"+"是知识的增加。so,它是让您花费5分钟以下的时间来提升您的知识储备量。
句幽
2020/04/27
6220
[译]使用DOT语言和GraphvizOnline来可视化你的ASP.NETCore3.0终结点01
这是系列文章中的第一篇:使用GraphvizOnline可视化ASP.NETCore3.0终结点。.
依乐祝
2020/07/17
2.4K0
[译]使用DOT语言和GraphvizOnline来可视化你的ASP.NETCore3.0终结点01
健康检查 - 从Readiness和Liveness 探针说起
本文主要是详细介绍K8S中的健康检查的2类方式, 即: 存活(liveness)探针和就绪(readiness)探针, 前者关乎pod是否要重启, 后者关乎service 端点列表是否要拿掉该pod. 介绍完之后并附上最佳实践案例, 涵盖: web server, tomcat等中间件, redis等缓存服务器, mysql等开源数据库, spring微服务...
东风微鸣
2022/04/21
4.2K0
健康检查 - 从Readiness和Liveness 探针说起
Asp.Net Core 中间件应用实战中你不知道的那些事
这篇文章主要分享Endpoint 终结点路由的中间件的应用场景及实践案例,不讲述其工作原理,如果需要了解工作原理的同学, 可以点击查看以下两篇解读文章:
Jlion
2022/04/07
9150
Asp.Net Core 中间件应用实战中你不知道的那些事
nacos与k8s service健康检查详解
在 Nacos 中,服务实例可能会在某些条件下自动下线(即被标记为不健康,并从可用实例列表中移除)。这种行为通常由以下机制控制:
锅总
2024/11/22
2840
nacos与k8s service健康检查详解
.NET Core 3.1之深入源码理解HealthCheck(二)
前文讨论了HealthCheck的理论部分,本文将讨论有关HealthCheck的应用内容。
AI.NET 极客圈
2020/05/18
9950
kubernetes系列教程(八)Pod健康检查机制
上一篇文章中kubernetes系列教程(七)深入玩转pod调度介绍了kubernetes中Pod的调度机制,通过实战演练介绍Pod调度到node的几种方法:1. 通过nodeName固定选择调度,2. 通过nodeSelector定向选择调度,3. 通过node Affinity亲和力调度,接下来介绍kubernetes系列教程pod的健康检查机制。
HappyLau谈云计算
2019/09/30
9.9K0
kubernetes系列教程(八)Pod健康检查机制
系统高可用之健康检查和健康度量那些事
随着人们的生活水平的不断提高,人们对身体健康越来越重视,很多人都做过体检,一般公司都会有一年一度的体检福利,健康体检是家喻户晓了。
2020labs小助手
2021/04/26
1.3K0
推荐阅读
相关推荐
Serilog高级玩法之用Serilog记录所选终结点附加属性
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验