目录
背景
这个想法是捕获执行时间并将其添加到响应标头中。执行时间1081毫秒将添加到响应标头中作为x-response-time: 1081ms。为此,我们可以使用中间件或过滤器,其中任何一个,或两者兼而有之。我见过类似的东西,称为Node.js的响应时间。下面是为ASP.NET Core执行操作的代码示例。
常见
这是秒表的接口,将在中间件/过滤器中用于计算执行时间ElapsedMilliseconds:
namespace Cpm.Web.Api.Core
{
public interface IStopwatch
{
long ElapsedMilliseconds { get; }
void Start();
void Stop();
void Reset();
}
}
中间件
在这里,在中间件中,我们使用注入的秒表IMiddlewareResponseTimeStopwatch,它已被注入为范围的。在处理之前或之后在Invoke中的Start()和Stop()秒表。通过时间差,我们可以得到执行时间。
using System.Diagnostics;
using Cpm.Web.Api.Core;
namespace Cpm.Web.Api.Middlewares
{
public class ResponseTimeMiddleware
{
private readonly RequestDelegate _next;
public ResponseTimeMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context,
IMiddlewareResponseTimeStopwatch watch)
{
watch.Start();
context.Response.OnStarting(state =>
{
watch.Stop();
string value = string.Format("{0}ms", watch.ElapsedMilliseconds);
context.Response.Headers["X-Response-Time"] = value;
return Task.CompletedTask;
}, context);
await _next(context);
}
}
public interface IMiddlewareResponseTimeStopwatch : IStopwatch
{
}
public class MiddlewareResponseTimeStopwatch : Stopwatch,
IMiddlewareResponseTimeStopwatch
{
public MiddlewareResponseTimeStopwatch() : base()
{
}
}
}
Action过滤器
过滤器类似于中间件,只是OnActionExecuting中的Start()和OnActionExecuted中的Stop()。IActionResponseTimeStopwatch也来自服务。
using Cpm.Web.Api.Core;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Diagnostics;
namespace Cpm.Web.Api.Filters
{
[AttributeUsage(validOn: AttributeTargets.Class | AttributeTargets.Method)]
public class ResponseTimeFilter : Attribute, IActionFilter
{
private IActionResponseTimeStopwatch GetStopwatch(HttpContext context)
{
return context.RequestServices.GetService<IActionResponseTimeStopwatch>();
}
public void OnActionExecuting(ActionExecutingContext context)
{
IStopwatch watch = GetStopwatch(context.HttpContext);
watch.Reset();
watch.Start();
}
public void OnActionExecuted(ActionExecutedContext context)
{
IStopwatch watch = GetStopwatch(context.HttpContext);
watch.Stop();
string value = string.Format("{0}ms", watch.ElapsedMilliseconds);
context.HttpContext.Response.Headers["X-Action-Response-Time"] = value;
}
}
public interface IActionResponseTimeStopwatch : IStopwatch
{
}
public class ActionResponseTimeStopwatch : Stopwatch, IActionResponseTimeStopwatch
{
public ActionResponseTimeStopwatch() : base()
{
}
}
}
使用中间件/过滤器
让我们在Startup.cs或bootstrap文件中使用过滤器和中间件。
添加过滤器
在void ConfigureServices(IServiceCollection services)中,完成依赖注入:
services.AddScoped<IActionResponseTimeStopwatch, ActionResponseTimeStopwatch>();
在void ConfigureServices(IServiceCollection services)中,添加以下内容:
/*Filter*/
services.AddMvc(options =>
{
options.Filters.Add(new ResponseTimeFilter());
});
此过滤器将应用于所有操作。
添加中间件
在void ConfigureServices(IServiceCollection services)中,完成依赖注入:
services.AddScoped<IMiddlewareResponseTimeStopwatch, MiddlewareResponseTimeStopwatch>();
在中void Configure(IApplicationBuilder app, IWebHostEnvironment env),添加以下内容:
/*Middleware*/
app.UseMiddleware<ResponseTimeMiddleware>();
测试中间件/过滤器
Curl
curl -X GET "https://localhost:7178/api/Hello" -H "accept: text/plain"
响应标头
content-type: application/json; charset=utf-8
date: Mon18 Jul 2022 10:25:18 GMT
server: Kestrel
x-action-response-time: 1008ms
x-response-time: 1081ms
x-trace-id: 0c635697-5606-4417-970f-6cdeebbc60ed
从过滤器添加x-action-response-time: 1008ms和从中间件中添加x-response-time: 1081ms。
重要
我们需要确保IActionResponseTimeStopwatch和IMiddlewareResponseTimeStopwatch注入为范围的,除了这个中间件和过滤器之外,没有其他人使用它们。
在中间件中,我们可以跳过注入和使用Stopwatch。
public async Task Invoke(HttpContext context)
{
var watch = new Stopwatch();
watch.Start();
/*others same*/
}
引用
- c# - Add Response Headers to ASP.NET Core Middleware - Stack Overflow
- Measuring And Reporting The Response Time Of An ASP.NET Core API
https://www.codeproject.com/Tips/5337523/Response-Time-Header-in-ASP-NET-Core