Поделиться через


Диагностика в Kestrel

Автор Сурабх Ширхатти

В этой статье приведены рекомендации по сбору диагностических данных из Kestrel для устранения неполадок. В книге рассматриваются такие темы:

  • Ведение журналов. Структурированные журналы записываются в систему ведения журналов .NET Core. Интерфейс ILogger используется платформами приложений для записи журналов, а пользователями — для ведения собственных журналов в приложении.
  • Метрики. Это представление мер данных за интервалы времени, например количество запросов в секунду. Метрики создаются с помощью EventCounter. Их можно отслеживать с использованием программы командной строки dotnet-counters или Application Insights.
  • DiagnosticSource.DiagnosticSource — это механизм для ведения журнала рабочего времени, который предоставляет богатый набор полезных данных для использования в процессе. В отличие от обычного ведения журнала, при котором данные должны выходить из процесса и иметь сериализуемый формат, DiagnosticSource хорошо работает со сложными данными.

Ведение журналов

Как и в большинство компонентов ASP.NET Core, Kestrelгенерирует сведения для журнала с помощью Microsoft.Extensions.Logging. Kestrel использует несколько категорий. Это позволяет выбирать журналы для прослушивания.

Имя категории ведения журнала События ведения журнала
Microsoft.AspNetCore.Server.Kestrel ApplicationError, ConnectionHeadResponseBodyWrite, ApplicationNeverCompleted, RequestBodyStart, RequestBodyDone, RequestBodyNotEntirelyRead, RequestBodyDrainTimedOut, ResponseMinimumDataRateNotSatisfied, InvalidResponseHeaderRemoved, HeartbeatSlow
Microsoft.AspNetCore.Server.Kestrel.BadRequests ConnectionBadRequest, RequestProcessingError, RequestBodyMinimumDataRateNotSatisfied
Microsoft.AspNetCore.Server.Kestrel.Connections ConnectionAccepted, ConnectionStart, ConnectionStop, ConnectionPause, ConnectionResume, ConnectionKeepAlive, ConnectionRejected, ConnectionDisconnect, NotAllConnectionsClosedGracefully, NotAllConnectionsAborted, ApplicationAbortedConnection
Microsoft.AspNetCore.Server.Kestrel.Http2 Http2ConnectionError, Http2ConnectionClosing, Http2ConnectionClosed, Http2StreamError, Http2StreamResetAbort, HPackDecodingError, HPackEncodingError, Http2FrameReceived, Http2FrameSending, Http2MaxConcurrentStreamsReached
Microsoft.AspNetCore.Server.Kestrel.Http3 Http3ConnectionError, Http3ConnectionClosing, Http3ConnectionClosed, Http3StreamAbort, Http3FrameReceived, Http3FrameSending

Ведение журнала подключения

Кроме того, Kestrel поддерживает возможность создавать журналы уровня Debug для обмена данными на уровне байтов. Ее можно включать отдельно для каждой конечной точки. Ведение журнала подключения описано в статье Настройка конечных точек для Kestrel.

Метрики

Метрики — это представление мер данных за интервалы времени, например количество запросов в секунду. Метрики позволяют отслеживать общее состояние приложения. Метрики Kestrel создаются с помощью EventCounter.

Примечание.

Счетчики connections-per-second и tls-handshakes-per-second имеют неправильное имя. Счетчики:

  • не всегда содержат число новых подключений или подтверждений TLS в секунду;
  • отображают число новых соединений или подтверждений TLS за последний интервал обновления, запрошенный получателем событий через аргумент EventCounterIntervalSec в filterPayload для KestrelEventSource.

Мы рекомендуем потребителям этих счетчиков масштабировать значение метрики из расчета параметра DisplayRateTimeScale, равного одной секунде.

Имя Отображаемое имя Description
connections-per-second Скорость подключения Число новых входящих подключений на интервал обновления
total-connections Total Connections Общее число подключений
tls-handshakes-per-second Скорость подтверждения TLS Количество новых подтверждений TLS за интервал обновления
total-tls-handshakes Всего подтверждений TLS Общее количество подтверждений TLS
current-tls-handshakes Текущие подтверждения TLS Количество обрабатываемых подтверждений TLS
failed-tls-handshakes Неудачные подтверждения TLS Общее число неудачных подтверждений TLS
current-connections Текущие подключения. Общее число подключений, включая неактивные
connection-queue-length Длина очереди подключений Общее число подключений, помещенных в очередь пула потоков. В работоспособной системе в стабильном состоянии это число всегда должно быть близко к нулю.
request-queue-length Длина очереди запросов Общее число запросов, помещенных в очередь пула потоков. В работоспособной системе в стабильном состоянии это число всегда должно быть близко к нулю. Указанная метрика отличается от очереди запросов IIS/Http.Sys. Эти метрики не сопоставимы.
current-upgraded-requests Текущие обновленные запросы (WebSockets) Число активных запросов WebSocket.

DiagnosticSource

Kestrel генерирует событие DiagnosticSource для запросов HTTP, отклоненных на уровне сервера, таких как неверно сформированные запросы и нарушения протоколов. Это означает, что такие запросы никогда не достигают уровня размещения в ASP.NET Core.

Kestrel выдает эти события с именем события Microsoft.AspNetCore.Server.Kestrel.BadRequest и с IFeatureCollection в качестве полезных данных объекта. Базовое исключение можно получить, обратившись к свойству IBadRequestExceptionFeature коллекции функций.

Обработка этих событий включает два этапа. Нужно создать наблюдатель для DiagnosticListener:

class BadRequestEventListener : IObserver<KeyValuePair<string, object>>, IDisposable
{
    private readonly IDisposable _subscription;
    private readonly Action<IBadRequestExceptionFeature> _callback;

    public BadRequestEventListener(DiagnosticListener diagnosticListener, Action<IBadRequestExceptionFeature> callback)
    {
        _subscription = diagnosticListener.Subscribe(this!, IsEnabled);
        _callback = callback;
    }
    private static readonly Predicate<string> IsEnabled = (provider) => provider switch
    {
        "Microsoft.AspNetCore.Server.Kestrel.BadRequest" => true,
        _ => false
    };
    public void OnNext(KeyValuePair<string, object> pair)
    {
        if (pair.Value is IFeatureCollection featureCollection)
        {
            var badRequestFeature = featureCollection.Get<IBadRequestExceptionFeature>();

            if (badRequestFeature is not null)
            {
                _callback(badRequestFeature);
            }
        }
    }
    public void OnError(Exception error) { }
    public void OnCompleted() { }
    public virtual void Dispose() => _subscription.Dispose();
}

Подпишитесь на ASP.NET Core DiagnosticListener, используя этот наблюдатель. В нашем примере мы создадим обратный вызов, с помощью которого в журнал записывается базовое исключение.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var diagnosticSource = app.Services.GetRequiredService<DiagnosticListener>();
using var badRequestListener = new BadRequestEventListener(diagnosticSource, (badRequestExceptionFeature) =>
{
    app.Logger.LogError(badRequestExceptionFeature.Error, "Bad request received");
});
app.MapGet("/", () => "Hello world");
app.Run();

Поведение с присоединенным отладчиком

Некоторые ограничения времени ожидания и скорости не применяются при присоединении отладчика к Kestrel процессу. Дополнительные сведения см. в разделе "Поведение с подключенным отладчиком".