Logging và diagnostics trong 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 (ghi nhật ký): Structured logs được ghi vào .NET logging.
ILoggerđược sử dụng bởi các app framework để ghi logs, và bởi users cho logging của riêng họ trong ứng dụng. - Metrics (chỉ số): Biểu diễn các đo lường dữ liệu theo khoảng thời gian, ví dụ như requests per second. Metrics data được phát ra bằng
EventCountervà có thể quan sát bằng công cụ dòng lệnh dotnet-counters hoặc với Application Insights. - DiagnosticSource:
DiagnosticSourcelà cơ chế ghi nhật ký thời gian production với các payload dữ liệu phong phú để tiêu thụ trong process. Không giống như logging, vốn giả định dữ liệu sẽ rời process và mong đợi dữ liệu có thể serialize,DiagnosticSourcehoạt động tốt với dữ liệu phức tạp.
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 Logging | Sự kiện Logging |
|---|---|
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 |
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-second và tls-handshakes-per-second được đặt tên không chính xác. Các counter này:
- Không luôn chứa số lượng kết nối mới hoặc TLS handshakes mỗi giây
- Hiển thị số lượng kết nối mới hoặc TLS handshakes trong khoảng cập nhật cuối cùng
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ên | Tên hiển thị | Mô tả |
|---|---|---|
connections-per-second | Connection Rate | Số kết nối đến mới mỗi khoảng cập nhật |
total-connections | Total Connections | Tổng số kết nối |
tls-handshakes-per-second | TLS Handshake Rate | Số TLS handshakes mới mỗi khoảng cập nhật |
total-tls-handshakes | Total TLS Handshakes | Tổng số TLS handshakes |
current-tls-handshakes | Current TLS Handshakes | Số TLS handshakes đang xử lý |
failed-tls-handshakes | Failed TLS Handshakes | Tổng số TLS handshakes thất bại |
current-connections | Current Connections | Tổng số kết nối, bao gồm các kết nối idle |
connection-queue-length | Connection Queue Length | Tổ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-length | Request Queue Length | Tổ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-requests | Current 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:
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:
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.