






















编写一个ASP.NET Core中间件,记录所有接口的执行耗时,当耗时超过500ms时,将请求报文(Header、Body)记录到异常日志中,支持依赖注入日志服务。
考察点:HttpContext操作、请求体回滚(EnableBuffering)、依赖注入(ILogger)、日志分级、资源释放。
public class RequestDurationMiddleware { private readonly RequestDelegate _next; private readonly ILogger<RequestDurationMiddleware> _logger; public RequestDurationMiddleware(RequestDelegate next, ILogger<RequestDurationMiddleware> logger) { _next = next; _logger = logger; } public async Task InvokeAsync(HttpContext context) { // 记录请求开始时间 var startTime = DateTime.Now; // 启用请求体回滚(默认请求体只能读取一次) context.Request.EnableBuffering(); try { // 执行下一个中间件(接口逻辑) await _next(context); } finally { // 计算执行耗时 var duration = DateTime.Now - startTime; var path = context.Request.Path; var method = context.Request.Method; // 记录耗时日志 _logger.LogInformation("接口 {Method} {Path} 执行耗时:{Duration}ms", method, path, duration.TotalMilliseconds.ToString("F2")); // 耗时超过500ms,记录请求报文 if (duration.TotalMilliseconds > 500) { // 读取请求头 var headers = context.Request.Headers.Select(h => $"{h.Key}: {string.Join(",", h.Value)}"); var headerStr = string.Join(Environment.NewLine, headers); // 读取请求体 string bodyStr = string.Empty; if (context.Request.ContentLength > 0) { // 重置请求体位置,避免后续中间件无法读取 context.Request.Body.Position = 0; using var reader = new StreamReader(context.Request.Body); bodyStr = await reader.ReadToEndAsync(); // 重置位置,供后续使用 context.Request.Body.Position = 0; } // 记录详细日志 _logger.LogWarning("接口 {Method} {Path} 耗时过长({Duration}ms),请求详情:{Environment.NewLine}请求头:{HeaderStr}{Environment.NewLine}请求体:{BodyStr}", method, path, duration.TotalMilliseconds.ToString("F2"), headerStr, bodyStr); } } } } // 扩展方法 public static class RequestDurationMiddlewareExtensions { public static IApplicationBuilder UseRequestDurationLogger(this IApplicationBuilder app) { return app.UseMiddleware<RequestDurationMiddleware>(); } }
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。