Partage via


Diagnostics dans Kestrel

De Sourabh Shirhatti

Cet article fournit des conseils pour la collecte de diagnostics à partir de Kestrel pour vous aider à résoudre les problèmes. Sont abordés les sujets suivants :

  • Journalisation : journaux structurés écrits dans la journalisation .NET Core. ILogger est utilisé par les frameworks d’application pour écrire des journaux, et par les utilisateurs pour leur propre journalisation dans une application.
  • Métriques : représentation des mesures de données sur des intervalles de temps, par exemple, le nombre de requêtes par seconde. Les métriques sont émises à l’aide de EventCounter et peuvent être observées à l’aide de l’outil en ligne de commande dotnet-counters ou avec Application Insights.
  • DiagnosticSource : DiagnosticSource est un mécanisme de journalisation au moment de la production avec des charges utiles de données enrichies pour la consommation dans le processus. Contrairement à la journalisation, qui suppose que les données quitteront le processus et attend des données sérialisables, DiagnosticSource fonctionne bien avec les données complexes.

Journalisation

Comme la plupart des composants dans ASP.NET Core, Kestrel utilise Microsoft.Extensions.Logging pour émettre des informations de journal. Kestrel utilise plusieurs catégories, ce qui vous permet d’être sélectif sur les journaux que vous écoutez.

Nom de la catégorie de journalisation Enregistrement des événements
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

Journalisation des connexions

Kestrel prend également en charge la possibilité d’émettre des journaux de niveau Debug pour la communication au niveau des octets et peut être activé par point de terminaison. Pour activer la journalisation des connexions, consultez Configurer des points de terminaison pour Kestrel

Mesures

Les métriques sont une représentation des mesures de données sur des intervalles de temps, par exemple, le nombre de requêtes par seconde. Les données de métriques permettent d’observer l’état d’une application à un niveau élevé. Les métriques Kestrel sont émises à l’aide de EventCounter.

Notes

Les compteurs connections-per-second et tls-handshakes-per-second sont nommés de manière incorrecte. Les compteurs :

  • Ne contiennent pas toujours le nombre de nouvelles connexions ou d’établissements de liaison TLS par seconde
  • Affichent le nombre de nouvelles connexions ou de nouvelles liaisons TLS dans l’intervalle de dernière mise à jour, comme demandé en tant que consommateur d’événements via l’argument EventCounterIntervalSec dans le filterPayload à KestrelEventSource.

Nous recommandons aux consommateurs de ces compteurs de mettre à l’échelle la valeur de la métrique en fonction de la valeur de DisplayRateTimeScale d’une seconde.

Nom Nom complet Description
connections-per-second Taux de connexions Nombre de nouvelles connexions entrantes par intervalle de mise à jour
total-connections Nombre total de connexions Nombre total de connexions
tls-handshakes-per-second Taux d’établissements de liaison TLS Nombre de nouvelles liaisons TLS par intervalle de mise à jour
total-tls-handshakes Nombre total de liaisons TLS Nombre total de liaisons TLS
current-tls-handshakes Liaisons TLS actuelles Nombre de liaisons TLS en cours
failed-tls-handshakes Échecs de liaison TLS Nombre total d’échecs de liaison TLS
current-connections Connexions courantes Nombre total de connexions, y compris les connexions inactives
connection-queue-length Longueur de la file d’attente de connexion Nombre total de connexions mises en file d’attente dans le pool de threads. Dans un système sain à l’état stable, ce nombre doit toujours être proche de zéro
request-queue-length Longueur de file d’attente de requêtes Nombre total de requêtes mises en file d’attente dans le pool de threads. Dans un système sain à l’état stable, ce nombre doit toujours être proche de zéro. Cette métrique est différente de la file d’attente de requêtes IIS/Http.Sys et ne peut pas être comparée
current-upgraded-requests Requêtes mises à niveau actuelles (WebSockets) Nombre de requêtes WebSocket actives

DiagnosticSource

Kestrel émet un événement DiagnosticSource pour les requêtes HTTP rejetées au niveau de la couche serveur, comme les requêtes incorrectes et les violations de protocole. Par conséquent, ces requêtes ne sont jamais intégrées à la couche d’hébergement d’ASP.NET Core.

Kestrel émet ces événements avec le nom d’événement Microsoft.AspNetCore.Server.Kestrel.BadRequest et un IFeatureCollection comme charge utile de l’objet. L’exception sous-jacente peut être récupérée en accédant à IBadRequestExceptionFeature sur la collection de fonctionnalités.

La résolution de ces événements est un processus en deux étapes. Un observateur pour DiagnosticListener doit être créé :

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

Abonnez-vous à ASP.NET Core DiagnosticListener avec l’observateur. Dans cet exemple, nous créons un rappel qui journalise l’exception sous-jacente.

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

Comportement avec le débogueur attaché

Certains délais d’expiration et limites de débit ne sont pas appliqués lorsqu’un débogueur est attaché à un processus Kestrel. Pour plus d’informations, consultez Comportement avec le débogueur attaché.