Note
此版本不是本文的最新版本。 有关当前版本,请参阅本文的 .NET 9 版本。
Warning
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 有关当前版本,请参阅本文的 .NET 9 版本。
Important
此信息与预发布产品相关,相应产品在商业发布之前可能会进行重大修改。 Microsoft 对此处提供的信息不提供任何明示或暗示的保证。
有关当前版本,请参阅本文的 .NET 9 版本。
本文提供从 Kestrel 收集诊断以帮助解决问题的指南。 涵盖的主题包括:
- 日志记录:写入 .NET 日志记录的结构化日志。 应用框架使用 ILogger 来编写日志,用户使用它在应用中进行用户自己的日志记录。
 - 指标:一段时间间隔内数据度量值的表示形式,例如每秒请求数。 指标是使用 
EventCounter发出的,可以使用 dotnet-counters 命令行工具或 Application Insights 进行观察。 - DiagnosticSource: 是一种用于记录生产时间的机制,具有丰富的数据有效负载可供进程使用。 与日志记录不同,后者假设数据将离开进程并且需要可序列化的数据,
DiagnosticSource可以很好地处理复杂数据。 
Logging
与 ASP.NET Core 中的大多数组件一样,Kestrel 使用 Microsoft.Extensions.Logging 发出日志信息。 
              Kestrel 使用多个类别,你可以选择要侦听的日志。
| 日志记录类别名称 | 日志记录事件 | 
|---|---|
Microsoft.AspNetCore.Server.Kestrel | 
              ApplicationError、、ConnectionHeadResponseBodyWrite、ApplicationNeverCompletedRequestBodyStart、RequestBodyDone、RequestBodyNotEntirelyRead、RequestBodyDrainTimedOut、ResponseMinimumDataRateNotSatisfied、、 InvalidResponseHeaderRemovedHeartbeatSlow | 
Microsoft.AspNetCore.Server.Kestrel.BadRequests | 
              ConnectionBadRequest、 RequestProcessingError、、 RequestBodyMinimumDataRateNotSatisfied | 
Microsoft.AspNetCore.Server.Kestrel.Connections | 
              ConnectionAccepted、、ConnectionStart、ConnectionStopConnectionPause、ConnectionResume、ConnectionKeepAlive、ConnectionRejectedConnectionDisconnect、、NotAllConnectionsClosedGracefully、、 NotAllConnectionsAbortedApplicationAbortedConnection | 
Microsoft.AspNetCore.Server.Kestrel.Http2 | 
              Http2ConnectionError、、Http2ConnectionClosing、Http2ConnectionClosedHttp2StreamError、Http2StreamResetAbort、HPackDecodingError、HPackEncodingError、Http2FrameReceived、、 Http2FrameSendingHttp2MaxConcurrentStreamsReached | 
Microsoft.AspNetCore.Server.Kestrel.Http3 | 
              Http3ConnectionError、、Http3ConnectionClosingHttp3ConnectionClosed、Http3StreamAbort、Http3FrameReceived、Http3FrameSending | 
连接日志记录
              Kestrel 还支持为字节级别的通信发出 Debug 级别日志,并可根据每个终结点启用该功能。 若要启用连接日志记录,请参阅为 Kestrel 配置终结点
Metrics
指标是一段时间间隔内数据度量值的表示形式,例如每秒请求数。 使用指标数据可以在高级别观察应用的状态。 
              Kestrel 指标是使用 EventCounter 发出的。
Note
              connections-per-second 和 tls-handshakes-per-second 计数器命名不正确。 计数器:
- 并不总是包含新建连接数或每秒 TLS 握手数
 - 显示上次更新间隔内新建连接数或 TLS 握手数,正如事件使用者通过 
EventCounterIntervalSec到filterPayload中的KestrelEventSource参数请求的那样。 
建议这些计数器的使用者按照 为一秒的情况来缩放指标值。
| Name | 显示名称 | Description | 
|---|---|---|
connections-per-second | 
连接速率 | 每个更新间隔的新传入连接数 | 
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 | 
当前升级请求 (Websocket) | 活动的 WebSocket 请求数 | 
DiagnosticSource
              Kestrel 为服务器层上被拒绝的 HTTP 请求发出 DiagnosticSource 事件,例如格式错误的请求和协议冲突。 因此,这些请求决不会进入 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 进程时,不会强制实施某些超时和速率限制。 有关详细信息,请参阅附加了调试器的行为。