如何用.NET Core自定义ILogger中间件捕获耗时超n毫秒的请求
解决.NET Core慢请求按Warning级别日志记录的方案
嘿,这个需求其实挺常见的,刚好可以通过自定义中间件来完美解决——毕竟默认的ASP.NET Core请求日志没法直接修改它的级别判断逻辑,咱们自己写个中间件来掌控整个流程就好啦!结合你已经实现了自定义ILogger的情况,下面是具体的实现步骤:
1. 创建慢请求日志中间件
这个中间件会在请求开始时记录时间,请求结束后计算耗时,再根据阈值决定日志级别:
public class SlowRequestLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger<SlowRequestLoggingMiddleware> _logger; private readonly int _slowRequestThresholdMs; // 注入必要的依赖:下一个中间件、日志实例、配置 public SlowRequestLoggingMiddleware(RequestDelegate next, ILogger<SlowRequestLoggingMiddleware> logger, IConfiguration configuration) { _next = next; _logger = logger; // 从配置读取慢请求阈值,默认设为500ms(可按需调整) _slowRequestThresholdMs = configuration.GetValue<int>("Logging:SlowRequestThresholdMs", 500); } public async Task InvokeAsync(HttpContext context) { // 记录请求开始时间(用UTC时间避免时区干扰) var startTime = DateTime.UtcNow; // 传递请求到后续中间件处理 await _next(context); // 计算总耗时 var elapsedMs = (DateTime.UtcNow - startTime).TotalMilliseconds; var statusCode = context.Response.StatusCode; var contentType = context.Response.ContentType; var requestMethod = context.Request.Method; var requestPath = context.Request.Path; // 根据阈值判断日志级别 if (elapsedMs > _slowRequestThresholdMs) { _logger.LogWarning( "Slow {RequestMethod} request to {RequestPath} finished in {ElapsedMs:F4}ms | StatusCode: {StatusCode} | ContentType: {ContentType}", requestMethod, requestPath, elapsedMs, statusCode, contentType); } else { // 如果需要保留常规请求的Info级别日志,就保留这段;如果默认日志已经记录,可注释避免重复 _logger.LogInformation( "{RequestMethod} request to {RequestPath} finished in {ElapsedMs:F4}ms | StatusCode: {StatusCode} | ContentType: {ContentType}", requestMethod, requestPath, elapsedMs, statusCode, contentType); } } }
2. 注册中间件并配置
在Program.cs中注册这个中间件,注意中间件顺序很重要,要让它包裹住整个请求处理流程:
var builder = WebApplication.CreateBuilder(args); // 注册你的自定义ILoggerProvider(替换成你已实现的Provider) builder.Logging.ClearProviders(); builder.Logging.AddProvider(new YourCustomLoggerProvider()); // 添加其他服务(比如控制器、授权等) builder.Services.AddControllers(); var app = builder.Build(); // 基础中间件(HTTPS重定向、静态文件等) app.UseHttpsRedirection(); app.UseStaticFiles(); // 注册慢请求日志中间件(放在路由之前,确保能捕获完整请求耗时) app.UseMiddleware<SlowRequestLoggingMiddleware>(); app.UseRouting(); app.UseAuthorization(); app.MapControllers(); app.Run();
然后在appsettings.json中配置阈值和生产环境的日志级别:
{ "Logging": { "SlowRequestThresholdMs": 500, // 自定义慢请求阈值,单位毫秒 "LogLevel": { "Default": "Warning", // 生产环境默认日志级别设为Warning "Microsoft.AspNetCore.Hosting.Diagnostics": "None", // 关闭默认的请求完成日志,避免重复输出 "Microsoft.AspNetCore": "Warning" } } }
3. 关键注意事项
- 中间件顺序:必须把慢请求中间件放在
UseRouting之前,这样才能捕获从请求进入到响应返回的完整耗时。 - 避免重复日志:默认的ASP.NET Core会通过
Microsoft.AspNetCore.Hosting.Diagnostics输出请求完成日志,所以我们把它的日志级别设为None,只保留自定义的日志输出。 - 自定义ILogger适配:因为我们已经通过
builder.Logging.AddProvider注册了你的自定义ILoggerProvider,中间件中的ILogger会自动使用你的实现,日志会输出到文本文件。 - 多环境配置:可以通过
appsettings.Production.json单独设置生产环境的阈值,比如把生产环境的阈值设为1000ms,开发环境设为500ms。
这样配置后,生产环境下只有耗时超过阈值的慢请求会以Warning级别记录,刚好符合你的需求~
内容的提问来源于stack exchange,提问作者pr.lwd
相关产品推荐
相关产品推荐

