如何判断当前请求的是健康检查 API

前言

为了性能监控的目的,我们使用了 Middleware 记录所有请求的 Log 。实现代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class RequestLoggingMiddleware
{
    ...
    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        finally
        {
            //Log
        }
    }
}

同时,我们在服务中加入了健康检查 API,用于定时访问检查服务状态。

这就导致 Log 中记录了大量健康检查 API 的日志,需要有方法判断出这类请求,并忽略日志写入。

判断路由地址

健康检查 API 的实现代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddHealthChecks();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{       
    // ...
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHealthChecks("/health");
        endpoints.MapControllers();
    });
}

因此,可以根据路由地址是否以 /health 开头来判断。

判断 DisplayName

上面的方法虽然可以实现要求,但是感觉太 low 了!

而且,如果把 Middleware 做成公共组件,那就不能限制健康检查 API 的路由地址的格式。

需要重新找到一个不变的数据值用于判断。

查看 Maphealthchecks 的实现代码,发现这样一句代码:

1
2
3
4
5
private static IEndpointConventionBuilder MapHealthChecksCore(IEndpointRouteBuilder endpoints, string pattern, HealthCheckOptions? options) 
{ 
    // ...
    return endpoints.Map(pattern, pipeline).WithDisplayName(DefaultDisplayName); 
} 

DisplayName 是个常量:

1
private const string DefaultDisplayName = "Health checks";

因此,我们只需判断 EndpointDisplayName 即可:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class RequestLoggingMiddleware
{
    ...
    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        finally
        {
            if (context.GetEndpoint()?.DisplayName == "Health checks")
            { 
            }
            else
            {
                //Log
            }
        }
    }
}
0%