Nguon: Microsoft Learn · .NET 8.0

Logging và diagnostics trong Kestrel

Nguồn: Logging and diagnostics in Kestrel

Tác giả: Sourabh Shirhatti

Bài viết này cung cấp hướng dẫn thu thập diagnostics (chẩn đoán) từ Kestrel để giúp khắc phục sự cố. Các chủ đề bao gồm:

Logging

Giống như hầu hết các thành phần trong ASP.NET Core, Kestrel sử dụng Microsoft.Extensions.Logging để phát ra thông tin log. Kestrel sử dụng nhiều categories cho phép bạn chọn lọc các logs bạn muốn nghe.

Tên Category LoggingSự kiện Logging
Microsoft.AspNetCore.Server.KestrelApplicationError, ConnectionHeadResponseBodyWrite, ApplicationNeverCompleted, RequestBodyStart, RequestBodyDone, RequestBodyNotEntirelyRead, RequestBodyDrainTimedOut, ResponseMinimumDataRateNotSatisfied, InvalidResponseHeaderRemoved, HeartbeatSlow
Microsoft.AspNetCore.Server.Kestrel.BadRequestsConnectionBadRequest, RequestProcessingError, RequestBodyMinimumDataRateNotSatisfied
Microsoft.AspNetCore.Server.Kestrel.ConnectionsConnectionAccepted, ConnectionStart, ConnectionStop, ConnectionPause, ConnectionResume, ConnectionKeepAlive, ConnectionRejected, ConnectionDisconnect, NotAllConnectionsClosedGracefully, NotAllConnectionsAborted, ApplicationAbortedConnection
Microsoft.AspNetCore.Server.Kestrel.Http2Http2ConnectionError, Http2ConnectionClosing, Http2ConnectionClosed, Http2StreamError, Http2StreamResetAbort, HPackDecodingError, HPackEncodingError, Http2FrameReceived, Http2FrameSending, Http2MaxConcurrentStreamsReached
Microsoft.AspNetCore.Server.Kestrel.Http3Http3ConnectionError, Http3ConnectionClosing, Http3ConnectionClosed, Http3StreamAbort, Http3FrameReceived, Http3FrameSending

Connection logging

Kestrel cũng hỗ trợ phát ra logs mức Debug cho giao tiếp ở cấp byte và có thể được bật trên từng endpoint. Để bật connection logging, xem configure endpoints for Kestrel.

Metrics

Metrics là biểu diễn các đo lường dữ liệu theo khoảng thời gian, ví dụ requests per second. Metrics data cho phép quan sát trạng thái của ứng dụng ở cấp cao. Kestrel metrics được phát ra bằng EventCounter.

Lưu ý: Các counter connections-per-secondtls-handshakes-per-second được đặt tên không chính xác. Các counter này:

Chúng tôi khuyến nghị người tiêu thụ các counter này chia giá trị metric dựa trên DisplayRateTimeScale là một giây.

TênTên hiển thịMô tả
connections-per-secondConnection RateSố kết nối đến mới mỗi khoảng cập nhật
total-connectionsTotal ConnectionsTổng số kết nối
tls-handshakes-per-secondTLS Handshake RateSố TLS handshakes mới mỗi khoảng cập nhật
total-tls-handshakesTotal TLS HandshakesTổng số TLS handshakes
current-tls-handshakesCurrent TLS HandshakesSố TLS handshakes đang xử lý
failed-tls-handshakesFailed TLS HandshakesTổng số TLS handshakes thất bại
current-connectionsCurrent ConnectionsTổng số kết nối, bao gồm các kết nối idle
connection-queue-lengthConnection Queue LengthTổng số kết nối đang xếp hàng vào thread pool. Trong hệ thống healthy ở trạng thái ổn định, con số này luôn gần bằng không
request-queue-lengthRequest Queue LengthTổng số requests đang xếp hàng vào thread pool. Trong hệ thống healthy ở trạng thái ổn định, con số này luôn gần bằng không. Metric này khác với IIS/Http.Sys request queue
current-upgraded-requestsCurrent Upgraded Requests (WebSockets)Số WebSocket requests đang hoạt động

DiagnosticSource

Kestrel phát ra sự kiện DiagnosticSource cho các HTTP request bị từ chối ở tầng server như các requests không đúng định dạng và vi phạm giao thức. Như vậy, các requests này không bao giờ lên đến tầng hosting của ASP.NET Core.

Kestrel phát ra các sự kiện này với tên sự kiện Microsoft.AspNetCore.Server.Kestrel.BadRequest và một IFeatureCollection là object payload. Exception cơ bản có thể được lấy bằng cách truy cập IBadRequestExceptionFeature trên feature collection.

Giải quyết các sự kiện này là quá trình hai bước. Trước tiên phải tạo observer cho DiagnosticListener:

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

Subscribe vào ASP.NET Core DiagnosticListener với observer. Trong ví dụ này, tạo callback để log exception cơ bản:

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

Hành vi khi đính kèm debugger

Một số timeout và rate limit không được thực thi khi có debugger đính kèm vào process Kestrel. Để biết thêm thông tin, xem Behavior with debugger attached.