Diagnostica in Kestrel

Di Sourabh Shirhatti

Questo articolo fornisce indicazioni per raccogliere la diagnostica da Kestrel per risolvere i problemi. Gli argomenti trattati includono:

  • Registrazione: log strutturati scritti nella registrazione di .NET Core. ILogger viene usato dai framework dell'app per scrivere i log e dagli utenti per la propria registrazione in un'app.
  • Metriche: rappresentazione delle misure dei dati in intervalli di tempo, ad esempio richieste al secondo. Le metriche vengono generate usando EventCounter e possono essere osservate usando lo strumento da riga di comando dotnet-counters o con Application Insights.
  • DiagnosticSource: DiagnosticSource è un meccanismo per la registrazione in fase di produzione con payload di dati avanzati per l'utilizzo all'interno del processo. A differenza della registrazione, che presuppone che i dati lascino il processo e si aspettano dati serializzabili, DiagnosticSource funzionano bene con dati complessi.

Registrazione

Analogamente alla maggior parte dei componenti in ASP.NET Core, Kestrel usa Microsoft.Extensions.Logging per generare informazioni di log. Kestrel utilizza l'uso di più categorie che consente di essere selettivi in base ai log a cui si è in ascolto.

Nome categoria registrazione Registrazione di eventi
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

registrazione Connessione ion

Kestrel supporta anche la possibilità di generare Debug log di livello per la comunicazione a livello di byte e può essere abilitato per ogni endpoint. Per abilitare la registrazione delle connessioni, vedere Configurare gli endpoint per Kestrel

Metriche

Le metriche sono una rappresentazione delle misure dei dati in intervalli di tempo, ad esempio le richieste al secondo. I dati delle metriche consentono di osservare lo stato di un'app a livello generale. Kestrel le metriche vengono generate usando EventCounter.

Nota

I connections-per-second contatori e tls-handshakes-per-second vengono denominati in modo non corretto. I contatori:

  • Non contenere sempre il numero di nuove connessioni o handshake TLS al secondo
  • Visualizzare il numero di nuove connessioni o handshake TLS nell'ultimo intervallo di aggiornamento come richiesto come consumer di eventi tramite l'argomento EventCounterIntervalSec in filterPayload a KestrelEventSource.

È consigliabile che i consumer di questi contatori ridimensionano il valore della metrica in base al DisplayRateTimeScale valore di un secondo.

Nome Nome visualizzato Descrizione
connections-per-second Connessione rate Numero di nuove connessioni in ingresso per intervallo di aggiornamento
total-connections Totale Connessione Numero totale di connessioni
tls-handshakes-per-second Frequenza handshake TLS Numero di nuovi handshake TLS per intervallo di aggiornamento
total-tls-handshakes Handshake TLS totali Numero totale di handshake TLS
current-tls-handshakes Handshake TLS correnti Numero di handshake TLS in corso
failed-tls-handshakes Handshake TLS non riuscito Numero totale di handshake TLS non riusciti
current-connections Current Connections (Connessioni correnti) Numero totale di connessioni, incluse le connessioni inattive
connection-queue-length lunghezza coda Connessione ion Numero totale di connessioni in coda al pool di thread. In uno stato stabile di un sistema integro, questo numero deve sempre essere vicino a zero
request-queue-length Lunghezza coda richiesta Numero totale di richieste accodate al pool di thread. In uno stato stabile di un sistema integro, questo numero deve sempre essere vicino a zero. Questa metrica è diversa dalla coda delle richieste IIS/Http.Sys e non può essere confrontata
current-upgraded-requests Richieste aggiornate correnti (WebSocket) Numero di richieste WebSocket attive

DiagnosticSource

Kestrel genera un DiagnosticSource evento per le richieste HTTP rifiutate a livello di server, ad esempio le richieste non valide e le violazioni dei protocolli. Di conseguenza, queste richieste non lo effettuano mai nel livello di hosting di ASP.NET Core.

Kestrel genera questi eventi con il nome dell'evento Microsoft.AspNetCore.Server.Kestrel.BadRequest e un IFeatureCollection oggetto come payload dell'oggetto. L'eccezione sottostante può essere recuperata accedendo a IBadRequestExceptionFeature nella raccolta di funzionalità.

La risoluzione di questi eventi è un processo in due passaggi. È necessario creare un osservatore per 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();
}

Sottoscrivere ASP.NET Core DiagnosticListener con l'osservatore. In questo esempio viene creato un callback che registra l'eccezione sottostante.

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();

Comportamento con debugger collegato

Alcuni timeout e limiti di frequenza non vengono applicati quando un debugger è collegato a un Kestrel processo. Per altre informazioni, vedere Comportamento con debugger collegato.