Skip to content

Commit be9f89e

Browse files
committed
Add exceeded max concurrent connections reason
1 parent 22f30c6 commit be9f89e

File tree

5 files changed

+42
-9
lines changed

5 files changed

+42
-9
lines changed

src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelMetrics.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ private void ConnectionStopCore(in ConnectionMetricsContext metricsContext, Exce
157157

158158
public void ConnectionRejected(in ConnectionMetricsContext metricsContext)
159159
{
160+
AddConnectionEndReason(metricsContext, ConnectionEndReason.MaxConcurrentConnectionsExceeded);
161+
160162
// Check live rather than cached state because this is just a counter, it's not a start/stop event like the other metrics.
161163
if (_rejectedConnectionsCounter.Enabled)
162164
{
@@ -509,6 +511,7 @@ internal static bool TryGetErrorType(ConnectionEndReason reason, [NotNullWhen(tr
509511
ConnectionEndReason.TlsOverHttp => "tls_over_http",
510512
ConnectionEndReason.MaxRequestBodySizeExceeded => "max_request_body_size_exceeded",
511513
ConnectionEndReason.UnexpectedEndOfRequestContent => "unexpected_end_of_request_content",
514+
ConnectionEndReason.MaxConcurrentConnectionsExceeded => "max_concurrent_connections_exceeded",
512515
_ => throw new InvalidOperationException($"Unable to calculate whether {reason} resolves to error.type value.")
513516
};
514517

src/Servers/Kestrel/test/FunctionalTests/ConnectionMiddlewareTests.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System;
5-
using System.Collections.Concurrent;
6-
using System.IO;
74
using System.IO.Pipelines;
85
using System.Net;
9-
using System.Threading;
10-
using System.Threading.Tasks;
6+
using Microsoft.AspNetCore.InternalTesting;
117
using Microsoft.AspNetCore.Server.Kestrel.Core;
128
using Microsoft.AspNetCore.Server.Kestrel.FunctionalTests;
13-
using Microsoft.AspNetCore.InternalTesting;
14-
using Xunit;
159

1610
#if SOCKETS
1711
namespace Microsoft.AspNetCore.Server.Kestrel.Sockets.FunctionalTests;

src/Servers/Kestrel/test/InMemory.FunctionalTests/ConnectionLimitTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public async Task RejectsConnectionsWhenLimitReached()
104104
{
105105
var testMeterFactory = new TestMeterFactory();
106106
using var rejectedConnections = new MetricCollector<long>(testMeterFactory, "Microsoft.AspNetCore.Server.Kestrel", "kestrel.rejected_connections");
107+
using var connectionDuration = new MetricCollector<double>(testMeterFactory, "Microsoft.AspNetCore.Server.Kestrel", "kestrel.connection.duration");
107108

108109
const int max = 10;
109110
var requestTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
@@ -149,6 +150,30 @@ public async Task RejectsConnectionsWhenLimitReached()
149150
}
150151
}
151152

153+
var measurements = connectionDuration.GetMeasurementSnapshot();
154+
155+
Assert.Collection(measurements,
156+
m => Assert.Equal(KestrelMetrics.GetErrorType(ConnectionEndReason.MaxConcurrentConnectionsExceeded), m.Tags[KestrelMetrics.ErrorType]),
157+
m => Assert.Equal(KestrelMetrics.GetErrorType(ConnectionEndReason.MaxConcurrentConnectionsExceeded), m.Tags[KestrelMetrics.ErrorType]),
158+
m => Assert.Equal(KestrelMetrics.GetErrorType(ConnectionEndReason.MaxConcurrentConnectionsExceeded), m.Tags[KestrelMetrics.ErrorType]),
159+
m => Assert.Equal(KestrelMetrics.GetErrorType(ConnectionEndReason.MaxConcurrentConnectionsExceeded), m.Tags[KestrelMetrics.ErrorType]),
160+
m => Assert.Equal(KestrelMetrics.GetErrorType(ConnectionEndReason.MaxConcurrentConnectionsExceeded), m.Tags[KestrelMetrics.ErrorType]),
161+
m => Assert.Equal(KestrelMetrics.GetErrorType(ConnectionEndReason.MaxConcurrentConnectionsExceeded), m.Tags[KestrelMetrics.ErrorType]),
162+
m => Assert.Equal(KestrelMetrics.GetErrorType(ConnectionEndReason.MaxConcurrentConnectionsExceeded), m.Tags[KestrelMetrics.ErrorType]),
163+
m => Assert.Equal(KestrelMetrics.GetErrorType(ConnectionEndReason.MaxConcurrentConnectionsExceeded), m.Tags[KestrelMetrics.ErrorType]),
164+
m => Assert.Equal(KestrelMetrics.GetErrorType(ConnectionEndReason.MaxConcurrentConnectionsExceeded), m.Tags[KestrelMetrics.ErrorType]),
165+
m => Assert.Equal(KestrelMetrics.GetErrorType(ConnectionEndReason.MaxConcurrentConnectionsExceeded), m.Tags[KestrelMetrics.ErrorType]),
166+
m => Assert.DoesNotContain(KestrelMetrics.ErrorType, m.Tags.Keys),
167+
m => Assert.DoesNotContain(KestrelMetrics.ErrorType, m.Tags.Keys),
168+
m => Assert.DoesNotContain(KestrelMetrics.ErrorType, m.Tags.Keys),
169+
m => Assert.DoesNotContain(KestrelMetrics.ErrorType, m.Tags.Keys),
170+
m => Assert.DoesNotContain(KestrelMetrics.ErrorType, m.Tags.Keys),
171+
m => Assert.DoesNotContain(KestrelMetrics.ErrorType, m.Tags.Keys),
172+
m => Assert.DoesNotContain(KestrelMetrics.ErrorType, m.Tags.Keys),
173+
m => Assert.DoesNotContain(KestrelMetrics.ErrorType, m.Tags.Keys),
174+
m => Assert.DoesNotContain(KestrelMetrics.ErrorType, m.Tags.Keys),
175+
m => Assert.DoesNotContain(KestrelMetrics.ErrorType, m.Tags.Keys));
176+
152177
static void AssertCounter(CollectedMeasurement<long> measurement) => Assert.Equal(1, measurement.Value);
153178
}
154179

src/Servers/Kestrel/test/InMemory.FunctionalTests/ConnectionMiddlewareTests.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
using Microsoft.AspNetCore.InternalTesting;
1717
using Microsoft.Extensions.Logging.Testing;
1818
using Xunit;
19+
using Microsoft.Extensions.Diagnostics.Metrics.Testing;
20+
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
1921

2022
namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests;
2123

@@ -150,10 +152,13 @@ public async Task ImmediateFinAfterOnConnectionAsyncClosesGracefully(RequestDele
150152
[MemberData(nameof(EchoAppRequestDelegates))]
151153
public async Task ImmediateFinAfterThrowingClosesGracefully(RequestDelegate requestDelegate)
152154
{
155+
var testMeterFactory = new TestMeterFactory();
156+
using var connectionDuration = new MetricCollector<double>(testMeterFactory, "Microsoft.AspNetCore.Server.Kestrel", "kestrel.connection.duration");
157+
153158
var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0));
154159
listenOptions.Use(next => context => throw new InvalidOperationException());
155160

156-
var serviceContext = new TestServiceContext(LoggerFactory);
161+
var serviceContext = new TestServiceContext(LoggerFactory, metrics: new KestrelMetrics(testMeterFactory));
157162

158163
await using (var server = new TestServer(requestDelegate, serviceContext, listenOptions))
159164
{
@@ -164,6 +169,11 @@ public async Task ImmediateFinAfterThrowingClosesGracefully(RequestDelegate requ
164169
await connection.WaitForConnectionClose();
165170
}
166171
}
172+
173+
Assert.Collection(connectionDuration.GetMeasurementSnapshot(), m =>
174+
{
175+
Assert.Equal(typeof(InvalidOperationException).FullName, m.Tags[KestrelMetrics.ErrorType]);
176+
});
167177
}
168178

169179
[Theory]

src/Shared/ServerInfrastructure/Http2/ConnectionEndReason.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,6 @@ internal enum ConnectionEndReason
4949
TlsHandshakeFailed,
5050
TlsOverHttp,
5151
MaxRequestBodySizeExceeded,
52-
UnexpectedEndOfRequestContent
52+
UnexpectedEndOfRequestContent,
53+
MaxConcurrentConnectionsExceeded
5354
}

0 commit comments

Comments
 (0)