diff --git a/NuGet.config b/NuGet.config index 9fede3245833..d37b12d22a3c 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,11 +4,12 @@ - + - - + + + @@ -26,11 +27,12 @@ - - + + + - + diff --git a/eng/Baseline.Designer.props b/eng/Baseline.Designer.props index 0b962449d9f1..0ca47e957b58 100644 --- a/eng/Baseline.Designer.props +++ b/eng/Baseline.Designer.props @@ -2,28 +2,28 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - - - + + + @@ -34,120 +34,120 @@ - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - - + + - 6.0.22 + 6.0.23 - - + + - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - + - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 @@ -155,114 +155,114 @@ - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - + - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - + - 6.0.22 + 6.0.23 - - + + - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - - + + - 6.0.22 + 6.0.23 - + - 6.0.22 + 6.0.23 - - - + + + - 6.0.22 + 6.0.23 - - + + - 6.0.22 + 6.0.23 - - + + - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - - + + @@ -270,7 +270,7 @@ - 6.0.22 + 6.0.23 @@ -278,50 +278,50 @@ - 6.0.22 + 6.0.23 - + - + - + - + - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - - + + @@ -331,8 +331,8 @@ - - + + @@ -340,8 +340,8 @@ - - + + @@ -352,58 +352,58 @@ - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - - + + - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - + - 6.0.22 + 6.0.23 @@ -411,71 +411,71 @@ - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - + - + - + - + - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - - + + - 6.0.22 + 6.0.23 - - + + - 6.0.22 + 6.0.23 @@ -491,195 +491,195 @@ - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - + - 6.0.22 + 6.0.23 - - + + - 6.0.22 + 6.0.23 - - + + - 6.0.22 + 6.0.23 - + - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - + - 6.0.22 + 6.0.23 - - + + - - + + - - + + - 6.0.22 + 6.0.23 - - + + - - + + - - + + - - + + - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - - - - + + + + - 6.0.22 + 6.0.23 @@ -688,69 +688,69 @@ - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - + - 6.0.22 + 6.0.23 - + - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 @@ -769,7 +769,7 @@ - 6.0.22 + 6.0.23 @@ -788,7 +788,7 @@ - 6.0.22 + 6.0.23 @@ -804,46 +804,46 @@ - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - - - + + + - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 @@ -853,7 +853,7 @@ - 6.0.22 + 6.0.23 @@ -862,73 +862,73 @@ - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - + - + - + - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 @@ -957,11 +957,11 @@ - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 @@ -979,13 +979,13 @@ - 6.0.22 + 6.0.23 - 6.0.22 + 6.0.23 - + \ No newline at end of file diff --git a/eng/Baseline.xml b/eng/Baseline.xml index 2984eef6c6e4..749cc484d04a 100644 --- a/eng/Baseline.xml +++ b/eng/Baseline.xml @@ -4,111 +4,111 @@ This file contains a list of all the packages and their versions which were rele Update this list when preparing for a new patch. --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 66cdb6dd76f1..86b6b375a58b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -9,37 +9,37 @@ --> - - https://dev.azure.com/dnceng/internal/_git/dotnet-efcore - 687fc8f9a538592b2b1494f6353293aac5da74a5 + + https://github.com/dotnet/efcore + 50a6896cca24b06e154bdf652c2e7aefd0dfb7a1 - - https://dev.azure.com/dnceng/internal/_git/dotnet-efcore - 687fc8f9a538592b2b1494f6353293aac5da74a5 + + https://github.com/dotnet/efcore + 50a6896cca24b06e154bdf652c2e7aefd0dfb7a1 - - https://dev.azure.com/dnceng/internal/_git/dotnet-efcore - 687fc8f9a538592b2b1494f6353293aac5da74a5 + + https://github.com/dotnet/efcore + 50a6896cca24b06e154bdf652c2e7aefd0dfb7a1 - - https://dev.azure.com/dnceng/internal/_git/dotnet-efcore - 687fc8f9a538592b2b1494f6353293aac5da74a5 + + https://github.com/dotnet/efcore + 50a6896cca24b06e154bdf652c2e7aefd0dfb7a1 - - https://dev.azure.com/dnceng/internal/_git/dotnet-efcore - 687fc8f9a538592b2b1494f6353293aac5da74a5 + + https://github.com/dotnet/efcore + 50a6896cca24b06e154bdf652c2e7aefd0dfb7a1 - - https://dev.azure.com/dnceng/internal/_git/dotnet-efcore - 687fc8f9a538592b2b1494f6353293aac5da74a5 + + https://github.com/dotnet/efcore + 50a6896cca24b06e154bdf652c2e7aefd0dfb7a1 - - https://dev.azure.com/dnceng/internal/_git/dotnet-efcore - 687fc8f9a538592b2b1494f6353293aac5da74a5 + + https://github.com/dotnet/efcore + 50a6896cca24b06e154bdf652c2e7aefd0dfb7a1 - - https://dev.azure.com/dnceng/internal/_git/dotnet-efcore - 687fc8f9a538592b2b1494f6353293aac5da74a5 + + https://github.com/dotnet/efcore + 50a6896cca24b06e154bdf652c2e7aefd0dfb7a1 https://github.com/dotnet/runtime @@ -177,9 +177,9 @@ https://github.com/dotnet/runtime 4822e3c3aa77eb82b2fb33c9321f923cf11ddde6 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 4bb6dc195c0a3bc4c7e24ff54a8925b98db4fecd + e0f0de876a67755a2c6cd2dc730c13f5959bdea8 https://dev.azure.com/dnceng/internal/_git/dotnet-runtime @@ -245,33 +245,33 @@ https://github.com/dotnet/runtime 4822e3c3aa77eb82b2fb33c9321f923cf11ddde6 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 4bb6dc195c0a3bc4c7e24ff54a8925b98db4fecd + e0f0de876a67755a2c6cd2dc730c13f5959bdea8 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 4bb6dc195c0a3bc4c7e24ff54a8925b98db4fecd + e0f0de876a67755a2c6cd2dc730c13f5959bdea8 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 4bb6dc195c0a3bc4c7e24ff54a8925b98db4fecd + e0f0de876a67755a2c6cd2dc730c13f5959bdea8 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 4bb6dc195c0a3bc4c7e24ff54a8925b98db4fecd + e0f0de876a67755a2c6cd2dc730c13f5959bdea8 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 4bb6dc195c0a3bc4c7e24ff54a8925b98db4fecd + e0f0de876a67755a2c6cd2dc730c13f5959bdea8 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 4bb6dc195c0a3bc4c7e24ff54a8925b98db4fecd + e0f0de876a67755a2c6cd2dc730c13f5959bdea8 diff --git a/eng/Versions.props b/eng/Versions.props index 84aeccf24dce..2186c0e1d1eb 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -9,7 +9,7 @@ 6 0 24 - false + true @@ -63,12 +63,12 @@ 6.0.0 - 6.0.22 - 6.0.22 - 6.0.22 - 6.0.22 - 6.0.22 - 6.0.22-servicing.23424.25 + 6.0.23 + 6.0.23 + 6.0.23 + 6.0.23 + 6.0.23 + 6.0.23-servicing.23480.2 6.0.0 6.0.1 6.0.0 @@ -103,7 +103,7 @@ 6.0.0 6.0.0 6.0.0 - 6.0.22-servicing.23424.25 + 6.0.23-servicing.23480.2 6.0.1 6.0.0 6.0.2 @@ -122,14 +122,14 @@ 6.0.11 - 6.0.22 - 6.0.22 - 6.0.22 - 6.0.22 - 6.0.22 - 6.0.22 - 6.0.22 - 6.0.22 + 6.0.23 + 6.0.23 + 6.0.23 + 6.0.23 + 6.0.23 + 6.0.23 + 6.0.23 + 6.0.23 6.0.0-beta.23408.5 6.0.0-beta.23408.5 diff --git a/global.json b/global.json index 4cc2acb633b1..83661f95122b 100644 --- a/global.json +++ b/global.json @@ -1,9 +1,9 @@ { "sdk": { - "version": "6.0.122" + "version": "6.0.123" }, "tools": { - "dotnet": "6.0.122", + "dotnet": "6.0.123", "runtimes": { "dotnet/x64": [ "2.1.30", diff --git a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs index ac3e9d166d4d..2e4a208fcc4e 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs @@ -33,6 +33,55 @@ internal partial class Http2Connection : IHttp2StreamLifetimeHandler, IHttpHeade private const PseudoHeaderFields _mandatoryRequestPseudoHeaderFields = PseudoHeaderFields.Method | PseudoHeaderFields.Path | PseudoHeaderFields.Scheme; + private const string MaximumEnhanceYourCalmCountProperty = "Microsoft.AspNetCore.Server.Kestrel.Http2.MaxEnhanceYourCalmCount"; + private const string MaximumFlowControlQueueSizeProperty = "Microsoft.AspNetCore.Server.Kestrel.Http2.MaxConnectionFlowControlQueueSize"; + + private static readonly int _enhanceYourCalmMaximumCount = GetMaximumEnhanceYourCalmCount(); + + private static int GetMaximumEnhanceYourCalmCount() + { + var data = AppContext.GetData(MaximumEnhanceYourCalmCountProperty); + if (data is int count) + { + return count; + } + if (data is string countStr && int.TryParse(countStr, out var parsed)) + { + return parsed; + } + + return 20; // Empirically derived + } + + // Accumulate _enhanceYourCalmCount over the course of EnhanceYourCalmTickWindowCount ticks. + // This should make bursts less likely to trigger disconnects. + private const int EnhanceYourCalmTickWindowCount = 5; + + private static bool IsEnhanceYourCalmEnabled => _enhanceYourCalmMaximumCount > 0; + + private static readonly int? ConfiguredMaximumFlowControlQueueSize = GetConfiguredMaximumFlowControlQueueSize(); + + private static int? GetConfiguredMaximumFlowControlQueueSize() + { + var data = AppContext.GetData(MaximumFlowControlQueueSizeProperty); + + if (data is int count) + { + return count; + } + + if (data is string countStr && int.TryParse(countStr, out var parsed)) + { + return parsed; + } + + return null; + } + + private readonly int _maximumFlowControlQueueSize; + + private bool IsMaximumFlowControlQueueSizeEnabled => _maximumFlowControlQueueSize > 0; + private readonly HttpConnectionContext _context; private readonly Http2FrameWriter _frameWriter; private readonly Pipe _input; @@ -40,7 +89,8 @@ internal partial class Http2Connection : IHttp2StreamLifetimeHandler, IHttpHeade private readonly int _minAllocBufferSize; private readonly HPackDecoder _hpackDecoder; private readonly InputFlowControl _inputFlowControl; - private readonly OutputFlowControl _outputFlowControl = new OutputFlowControl(new MultipleAwaitableProvider(), Http2PeerSettings.DefaultInitialWindowSize); + private readonly OutputFlowControl _outputFlowControl; + private readonly AwaitableProvider _outputFlowControlAwaitableProvider; // Keep our own reference so we can track queue size private readonly Http2PeerSettings _serverSettings = new Http2PeerSettings(); private readonly Http2PeerSettings _clientSettings = new Http2PeerSettings(); @@ -59,6 +109,9 @@ internal partial class Http2Connection : IHttp2StreamLifetimeHandler, IHttpHeade private int _clientActiveStreamCount; private int _serverActiveStreamCount; + private int _enhanceYourCalmCount; + private int _tickCount; + // The following are the only fields that can be modified outside of the ProcessRequestsAsync loop. private readonly ConcurrentQueue _completedStreams = new ConcurrentQueue(); private readonly StreamCloseAwaitable _streamCompletionAwaitable = new StreamCloseAwaitable(); @@ -88,6 +141,9 @@ public Http2Connection(HttpConnectionContext context) // Capture the ExecutionContext before dispatching HTTP/2 middleware. Will be restored by streams when processing request _context.InitialExecutionContext = ExecutionContext.Capture(); + _outputFlowControlAwaitableProvider = new MultipleAwaitableProvider(); + _outputFlowControl = new OutputFlowControl(_outputFlowControlAwaitableProvider, Http2PeerSettings.DefaultInitialWindowSize); + _frameWriter = new Http2FrameWriter( context.Transport.Output, context.ConnectionContext, @@ -129,6 +185,17 @@ public Http2Connection(HttpConnectionContext context) _serverSettings.MaxHeaderListSize = (uint)httpLimits.MaxRequestHeadersTotalSize; _serverSettings.InitialWindowSize = (uint)http2Limits.InitialStreamWindowSize; + _maximumFlowControlQueueSize = ConfiguredMaximumFlowControlQueueSize is null + ? 4 * http2Limits.MaxStreamsPerConnection // 4 is a magic number to give us some padding above the expected maximum size + : (int)ConfiguredMaximumFlowControlQueueSize; + + var minimumMaximumFlowControlQueueSize = 2 * http2Limits.MaxStreamsPerConnection; // Double to match 7.0 and 8.0 + if (IsMaximumFlowControlQueueSizeEnabled && _maximumFlowControlQueueSize < minimumMaximumFlowControlQueueSize) + { + Log.Http2FlowControlQueueMaximumTooLow(context.ConnectionId, minimumMaximumFlowControlQueueSize, _maximumFlowControlQueueSize); + _maximumFlowControlQueueSize = minimumMaximumFlowControlQueueSize; + } + // Start pool off at a smaller size if the max number of streams is less than the InitialStreamPoolSize StreamPool = new PooledStreamStack(Math.Min(InitialStreamPoolSize, http2Limits.MaxStreamsPerConnection)); @@ -352,13 +419,20 @@ public async Task ProcessRequestsAsync(IHttpApplication appl stream.Abort(new IOException(CoreStrings.Http2StreamAborted, connectionError)); } - // Use the server _serverActiveStreamCount to drain all requests on the server side. - // Can't use _clientActiveStreamCount now as we now decrement that count earlier/ - // Can't use _streams.Count as we wait for RST/END_STREAM before removing the stream from the dictionary - while (_serverActiveStreamCount > 0) + // For some reason, this loop doesn't terminate when we're trying to abort. + // Since we're making a narrow fix for a patch, we'll bypass it in such scenarios. + // TODO: This is probably a bug - something in here should probably detect aborted + // connections and short-circuit. + if (!(IsEnhanceYourCalmEnabled || IsMaximumFlowControlQueueSizeEnabled) || error is not Http2ConnectionErrorException) { - await _streamCompletionAwaitable; - UpdateCompletedStreams(); + // Use the server _serverActiveStreamCount to drain all requests on the server side. + // Can't use _clientActiveStreamCount now as we now decrement that count earlier/ + // Can't use _streams.Count as we wait for RST/END_STREAM before removing the stream from the dictionary + while (_serverActiveStreamCount > 0) + { + await _streamCompletionAwaitable; + UpdateCompletedStreams(); + } } while (StreamPool.TryPop(out var pooledStream)) @@ -1053,6 +1127,20 @@ private void StartStream() throw new Http2StreamErrorException(_currentHeadersStream.StreamId, CoreStrings.Http2ErrorMaxStreams, Http2ErrorCode.REFUSED_STREAM); } + if (IsMaximumFlowControlQueueSizeEnabled && _outputFlowControlAwaitableProvider.ActiveCount > _maximumFlowControlQueueSize) + { + Log.Http2FlowControlQueueOperationsExceeded(_context.ConnectionId, _maximumFlowControlQueueSize); + + // Now that we've logged a useful message, we can put vague text in the exception + // messages in case they somehow make it back to the client (not expected) + + // This will close the socket - we want to do that right away + Abort(new ConnectionAbortedException("HTTP/2 connection exceeded the outgoing flow control maximum queue size.")); + + // Throwing an exception as well will help us clean up on our end more quickly by (e.g.) skipping processing of already-buffered input + throw new Http2ConnectionErrorException(CoreStrings.Http2ConnectionFaulted, Http2ErrorCode.INTERNAL_ERROR); + } + // We don't use the _serverActiveRequestCount here as during shutdown, it and the dictionary counts get out of sync. // The streams still exist in the dictionary until the client responds with a RST or END_STREAM. // Also, we care about the dictionary size for too much memory consumption. @@ -1061,6 +1149,20 @@ private void StartStream() // Server is getting hit hard with connection resets. // Tell client to calm down. // TODO consider making when to send ENHANCE_YOUR_CALM configurable? + + if (IsEnhanceYourCalmEnabled && Interlocked.Increment(ref _enhanceYourCalmCount) > EnhanceYourCalmTickWindowCount * _enhanceYourCalmMaximumCount) + { + Log.Http2TooManyEnhanceYourCalms(_context.ConnectionId, _enhanceYourCalmMaximumCount); + + // Now that we've logged a useful message, we can put vague text in the exception + // messages in case they somehow make it back to the client (not expected) + + // This will close the socket - we want to do that right away + Abort(new ConnectionAbortedException(CoreStrings.Http2ConnectionFaulted)); + // Throwing an exception as well will help us clean up on our end more quickly by (e.g.) skipping processing of already-buffered input + throw new Http2ConnectionErrorException(CoreStrings.Http2ConnectionFaulted, Http2ErrorCode.ENHANCE_YOUR_CALM); + } + throw new Http2StreamErrorException(_currentHeadersStream.StreamId, CoreStrings.Http2TellClientToCalmDown, Http2ErrorCode.ENHANCE_YOUR_CALM); } } @@ -1123,6 +1225,12 @@ private void AbortStream(int streamId, IOException error) void IRequestProcessor.Tick(DateTimeOffset now) { Input.CancelPendingRead(); + // We count EYCs over a window of a given length to avoid flagging short-lived bursts. + // At the end of each window, reset the count. + if (IsEnhanceYourCalmEnabled && ++_tickCount % EnhanceYourCalmTickWindowCount == 0) + { + Interlocked.Exchange(ref _enhanceYourCalmCount, 0); + } } void IHttp2StreamLifetimeHandler.OnStreamCompleted(Http2Stream stream) diff --git a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/IKestrelTrace.cs b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/IKestrelTrace.cs index 6a75f4657b14..28b7b5cd8b05 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/IKestrelTrace.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/IKestrelTrace.cs @@ -78,8 +78,14 @@ internal interface IKestrelTrace : ILogger void Http2FrameSending(string connectionId, Http2Frame frame); + void Http2TooManyEnhanceYourCalms(string connectionId, int count); + void Http2MaxConcurrentStreamsReached(string connectionId); + void Http2FlowControlQueueOperationsExceeded(string connectionId, int count); + + void Http2FlowControlQueueMaximumTooLow(string connectionId, int expected, int actual); + void InvalidResponseHeaderRemoved(); void Http3ConnectionError(string connectionId, Http3ConnectionErrorException ex); diff --git a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelTrace.cs b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelTrace.cs index 3c3b7bc4af07..c1a6021549f5 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelTrace.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelTrace.cs @@ -395,6 +395,30 @@ public void Http3GoAwayStreamId(string connectionId, long goAwayStreamId) Http3GoAwayStreamId(_http3Logger, connectionId, goAwayStreamId); } + [LoggerMessage(54, LogLevel.Debug, @"Connection id ""{ConnectionId}"" aborted since at least {Count} ENHANCE_YOUR_CALM responses were recorded per second.", EventName = "Http2TooManyEnhanceYourCalms")] + private static partial void Http2TooManyEnhanceYourCalms(ILogger logger, string connectionId, int count); + + public void Http2TooManyEnhanceYourCalms(string connectionId, int count) + { + Http2TooManyEnhanceYourCalms(_http2Logger, connectionId, count); + } + + [LoggerMessage(55, LogLevel.Debug, @"Connection id ""{ConnectionId}"" exceeded the output flow control maximum queue size of {Count}.", EventName = "Http2FlowControlQueueOperationsExceeded")] + private static partial void Http2FlowControlQueueOperationsExceeded(ILogger logger, string connectionId, int count); + + public void Http2FlowControlQueueOperationsExceeded(string connectionId, int count) + { + Http2FlowControlQueueOperationsExceeded(_http3Logger, connectionId, count); + } + + [LoggerMessage(56, LogLevel.Debug, @"Connection id ""{ConnectionId}"" configured maximum flow control queue size {Actual} is less than double the maximum streams per connection {Expected}. Increasing configured value to {Expected}.", EventName = "Http2FlowControlQueueMaximumTooLow")] + private static partial void Http2FlowControlQueueMaximumTooLow(ILogger logger, string connectionId, int expected, int actual); + + public void Http2FlowControlQueueMaximumTooLow(string connectionId, int expected, int actual) + { + Http2FlowControlQueueMaximumTooLow(_http3Logger, connectionId, expected, actual); + } + public virtual void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) => _generalLogger.Log(logLevel, eventId, state, exception, formatter); diff --git a/src/Servers/Kestrel/perf/Microbenchmarks/Mocks/MockTrace.cs b/src/Servers/Kestrel/perf/Microbenchmarks/Mocks/MockTrace.cs index 7a87e2ee4041..c9052461b9ed 100644 --- a/src/Servers/Kestrel/perf/Microbenchmarks/Mocks/MockTrace.cs +++ b/src/Servers/Kestrel/perf/Microbenchmarks/Mocks/MockTrace.cs @@ -59,7 +59,10 @@ public void Http2ConnectionClosing(string connectionId) { } public void Http2ConnectionClosed(string connectionId, int highestOpenedStreamId) { } public void Http2FrameReceived(string connectionId, Http2Frame frame) { } public void Http2FrameSending(string connectionId, Http2Frame frame) { } + public void Http2TooManyEnhanceYourCalms(string connectionId, int count) { } public void Http2MaxConcurrentStreamsReached(string connectionId) { } + public void Http2FlowControlQueueOperationsExceeded(string connectionId, int count) { } + public void Http2FlowControlQueueMaximumTooLow(string connectionId, int expected, int actual) { } public void InvalidResponseHeaderRemoved() { } public void Http3ConnectionError(string connectionId, Http3ConnectionErrorException ex) { } public void Http3ConnectionClosing(string connectionId) { } diff --git a/src/Servers/Kestrel/samples/Http2SampleApp/Http2SampleApp.csproj b/src/Servers/Kestrel/samples/Http2SampleApp/Http2SampleApp.csproj index cc404533ad8f..d0930e69fee0 100644 --- a/src/Servers/Kestrel/samples/Http2SampleApp/Http2SampleApp.csproj +++ b/src/Servers/Kestrel/samples/Http2SampleApp/Http2SampleApp.csproj @@ -1,4 +1,4 @@ - + $(DefaultNetCoreTargetFramework) diff --git a/src/Servers/Kestrel/shared/test/CompositeKestrelTrace.cs b/src/Servers/Kestrel/shared/test/CompositeKestrelTrace.cs index 523e77a059ac..1245abfd2a4b 100644 --- a/src/Servers/Kestrel/shared/test/CompositeKestrelTrace.cs +++ b/src/Servers/Kestrel/shared/test/CompositeKestrelTrace.cs @@ -234,12 +234,30 @@ public void Http2FrameSending(string connectionId, Http2Frame frame) _trace2.Http2FrameSending(connectionId, frame); } + public void Http2TooManyEnhanceYourCalms(string connectionId, int count) + { + _trace1.Http2TooManyEnhanceYourCalms(connectionId, count); + _trace2.Http2TooManyEnhanceYourCalms(connectionId, count); + } + public void Http2MaxConcurrentStreamsReached(string connectionId) { _trace1.Http2MaxConcurrentStreamsReached(connectionId); _trace2.Http2MaxConcurrentStreamsReached(connectionId); } + public void Http2FlowControlQueueOperationsExceeded(string connectionId, int count) + { + _trace1.Http2FlowControlQueueOperationsExceeded(connectionId, count); + _trace2.Http2FlowControlQueueOperationsExceeded(connectionId, count); + } + + public void Http2FlowControlQueueMaximumTooLow(string connectionId, int expected, int actual) + { + _trace1.Http2FlowControlQueueMaximumTooLow(connectionId, expected, actual); + _trace2.Http2FlowControlQueueMaximumTooLow(connectionId, expected, actual); + } + public void InvalidResponseHeaderRemoved() { _trace1.InvalidResponseHeaderRemoved();