Приведи пример использования middleware для вычисления времени выполнения каждого запроса
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Пример Middleware для вычисления времени выполнения запроса в ASP.NET Core
В ASP.NET Core middleware — это компоненты, которые образуют конвейер обработки HTTP-запросов. Каждый middleware может выполнять операции до и после следующего компонента в цепочке. Это идеально подходит для вычисления времени выполнения запроса, так как мы можем зафиксировать время в начале конвейера и вычислить разницу после выполнения остальных компонентов.
Реализация Middleware
Создадим класс RequestTimingMiddleware, который будет измерять время выполнения:
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
public class RequestTimingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<RequestTimingMiddleware> _logger;
public RequestTimingMiddleware(RequestDelegate next, ILogger<RequestTimingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
// Создаем Stopwatch для точного измерения времени
var stopwatch = Stopwatch.StartNew();
try
{
// Вызываем следующий middleware в конвейере
await _next(context);
}
finally
{
// Останавливаем таймер после завершения обработки
stopwatch.Stop();
// Получаем общее время выполнения
var elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
// Логируем информацию о запросе и времени выполнения
_logger.LogInformation(
"Request {Method} {Path} completed in {ElapsedMs} ms with status {StatusCode}",
context.Request.Method,
context.Request.Path,
elapsedMilliseconds,
context.Response.StatusCode);
// Также можно добавить заголовок с временем выполнения для клиента
context.Response.Headers.Add("X-Request-Duration", $"{elapsedMilliseconds}ms");
}
}
}
Регистрация Middleware
Middleware нужно зарегистрировать в конвейере обработки запросов. Обычно это делается в классе Program.cs или Startup.cs:
// В Program.cs (для .NET 6+)
var builder = WebApplication.CreateBuilder(args);
// Добавляем сервисы
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Регистрируем middleware в начале конвейера
app.UseMiddleware<RequestTimingMiddleware>();
// Другие middleware
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Улучшенная версия с дополнительными возможностями
Для production-среды можно создать более продвинутую версию middleware:
public class AdvancedRequestTimingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<AdvancedRequestTimingMiddleware> _logger;
private readonly RequestTimingOptions _options;
public AdvancedRequestTimingMiddleware(
RequestDelegate next,
ILogger<AdvancedRequestTimingMiddleware> logger,
IOptions<RequestTimingOptions> options)
{
_next = next;
_logger = logger;
_options = options.Value;
}
public async Task InvokeAsync(HttpContext context)
{
// Пропускаем определенные пути (например, health checks)
if (_options.ExcludedPaths.Any(path =>
context.Request.Path.StartsWithSegments(path)))
{
await _next(context);
return;
}
var stopwatch = Stopwatch.StartNew();
try
{
await _next(context);
}
finally
{
stopwatch.Stop();
var elapsedMs = stopwatch.ElapsedMilliseconds;
// Используем разные уровни логирования в зависимости от времени выполнения
if (elapsedMs > _options.SlowRequestThreshold)
{
_logger.LogWarning(
"SLOW REQUEST: {Method} {Path} took {ElapsedMs}ms (Threshold: {Threshold}ms)",
context.Request.Method,
context.Request.Path,
elapsedMs,
_options.SlowRequestThreshold);
}
else
{
_logger.LogInformation(
"Request {Method} {Path} completed in {ElapsedMs}ms",
context.Request.Method,
context.Request.Path,
elapsedMs);
}
// Добавляем метрики для систем мониторинга
if (_options.EnableMetrics)
{
// Здесь можно интегрировать с Application Insights, Prometheus и т.д.
MetricsCollector.RecordRequestDuration(
context.Request.Path,
elapsedMs,
context.Response.StatusCode);
}
}
}
}
public class RequestTimingOptions
{
public long SlowRequestThreshold { get; set; } = 500; // 500ms
public bool EnableMetrics { get; set; } = true;
public string[] ExcludedPaths { get; set; } = new[] { "/health", "/metrics" };
}
Ключевые особенности реализации:
- Использование Stopwatch - предоставляет наиболее точное измерение времени в .NET
- Блок try-finally - гарантирует, что время будет зафиксировано даже при исключениях
- Логирование - запись времени выполнения для последующего анализа
- Добавление HTTP-заголовков - возможность передать информацию клиенту
- Гибкость - возможность настройки через options pattern
Преимущества подхода:
- Низкие накладные расходы - middleware добавляет минимальную нагрузку
- Централизованная логика - все запросы обрабатываются одинаково
- Гибкость - легко добавить дополнительные функции (фильтрация, метрики, алертинг)
- Интеграция с экосистемой - совместимость с другими middleware и системой логирования
Практическое применение:
Такой middleware полезен для:
- Выявления медленных эндпоинтов
- Мониторинга производительности API
- Отладки проблем с производительностью
- Сбора метрик для систем мониторинга (Grafana, Azure Monitor)
- Настройки алертинга при превышении пороговых значений
Middleware для измерения времени выполнения — это стандартный паттерн в ASP.NET Core, который демонстрирует мощь и гибкость конвейера обработки запросов, позволяя легко добавлять сквозную функциональность без модификации бизнес-логики приложения.