← Назад к вопросам

Приведи пример использования middleware для вычисления времени выполнения каждого запроса

1.0 Junior🔥 62 комментариев
#ASP.NET и Web API

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Пример 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" };
}

Ключевые особенности реализации:

  1. Использование Stopwatch - предоставляет наиболее точное измерение времени в .NET
  2. Блок try-finally - гарантирует, что время будет зафиксировано даже при исключениях
  3. Логирование - запись времени выполнения для последующего анализа
  4. Добавление HTTP-заголовков - возможность передать информацию клиенту
  5. Гибкость - возможность настройки через options pattern

Преимущества подхода:

  • Низкие накладные расходы - middleware добавляет минимальную нагрузку
  • Централизованная логика - все запросы обрабатываются одинаково
  • Гибкость - легко добавить дополнительные функции (фильтрация, метрики, алертинг)
  • Интеграция с экосистемой - совместимость с другими middleware и системой логирования

Практическое применение:

Такой middleware полезен для:

  • Выявления медленных эндпоинтов
  • Мониторинга производительности API
  • Отладки проблем с производительностью
  • Сбора метрик для систем мониторинга (Grafana, Azure Monitor)
  • Настройки алертинга при превышении пороговых значений

Middleware для измерения времени выполнения — это стандартный паттерн в ASP.NET Core, который демонстрирует мощь и гибкость конвейера обработки запросов, позволяя легко добавлять сквозную функциональность без модификации бизнес-логики приложения.