diff --git a/src/TelemetryConsumption/Kestrel/IKestrelTelemetryConsumer.cs b/src/TelemetryConsumption/Kestrel/IKestrelTelemetryConsumer.cs
index 26b99773b..62bd503ed 100644
--- a/src/TelemetryConsumption/Kestrel/IKestrelTelemetryConsumer.cs
+++ b/src/TelemetryConsumption/Kestrel/IKestrelTelemetryConsumer.cs
@@ -10,6 +10,22 @@ namespace Yarp.Telemetry.Consumption;
///
public interface IKestrelTelemetryConsumer
{
+ ///
+ /// Called at the start of a connection.
+ ///
+ /// Timestamp when the event was fired.
+ /// ID of the connection.
+ /// Local endpoint for the connection.
+ /// Remote endpoint for the connection.
+ void OnConnectionStart(DateTime timestamp, string connectionId, string localEndPoint, string remoteEndPoint) { }
+
+ ///
+ /// Called at the end of a connection.
+ ///
+ /// Timestamp when the event was fired.
+ /// ID of the connection.
+ void OnConnectionStop(DateTime timestamp, string connectionId) { }
+
///
/// Called at the start of a request.
///
diff --git a/src/TelemetryConsumption/Kestrel/KestrelEventListenerService.cs b/src/TelemetryConsumption/Kestrel/KestrelEventListenerService.cs
index 2d0b5f4f7..afd086a22 100644
--- a/src/TelemetryConsumption/Kestrel/KestrelEventListenerService.cs
+++ b/src/TelemetryConsumption/Kestrel/KestrelEventListenerService.cs
@@ -28,6 +28,30 @@ protected override void OnEvent(IKestrelTelemetryConsumer[] consumers, EventWrit
switch (eventData.EventId)
{
+ case 1:
+ Debug.Assert(eventData.EventName == "ConnectionStart" && payload.Count == 3);
+ {
+ var connectionId = (string)payload[0];
+ var LocalEndPoint = (string)payload[1];
+ var remoteEndPoint = (string)payload[2];
+ foreach (var consumer in consumers)
+ {
+ consumer.OnConnectionStart(eventData.TimeStamp, connectionId, LocalEndPoint, remoteEndPoint);
+ }
+ }
+ break;
+
+ case 2:
+ Debug.Assert(eventData.EventName == "ConnectionStop" && payload.Count == 1);
+ {
+ var connectionId = (string)payload[0];
+ foreach (var consumer in consumers)
+ {
+ consumer.OnConnectionStop(eventData.TimeStamp, connectionId);
+ }
+ }
+ break;
+
case 3:
Debug.Assert(eventData.EventName == "RequestStart" && payload.Count == 5);
{
diff --git a/test/ReverseProxy.FunctionalTests/TelemetryConsumptionTests.cs b/test/ReverseProxy.FunctionalTests/TelemetryConsumptionTests.cs
index b89b17c93..3b595b11c 100644
--- a/test/ReverseProxy.FunctionalTests/TelemetryConsumptionTests.cs
+++ b/test/ReverseProxy.FunctionalTests/TelemetryConsumptionTests.cs
@@ -123,6 +123,7 @@ await test.Invoke(async uri =>
var expected = new[]
{
+ "OnConnectionStart-Kestrel",
"OnRequestStart-Kestrel",
"OnForwarderInvoke",
"OnForwarderStart",
@@ -144,6 +145,7 @@ await test.Invoke(async uri =>
"OnContentTransferred",
"OnForwarderStop",
"OnRequestStop-Kestrel",
+ "OnConnectionStop-Kestrel",
};
if (!useHttpsOnDestination)
@@ -283,8 +285,10 @@ public void OnRequestStart(DateTime timestamp, string scheme, string host, int p
public void OnConnectStart(DateTime timestamp, string address) => AddStage(nameof(OnConnectStart), timestamp);
public void OnConnectStop(DateTime timestamp) => AddStage(nameof(OnConnectStop), timestamp);
public void OnConnectFailed(DateTime timestamp, SocketError error, string exceptionMessage) => AddStage(nameof(OnConnectFailed), timestamp);
+ public void OnConnectionStart(DateTime timestamp, string connectionId, string localEndPoint, string remoteEndPoint) => AddStage($"{nameof(OnConnectionStart)}-Kestrel", timestamp);
public void OnRequestStart(DateTime timestamp, string connectionId, string requestId, string httpVersion, string path, string method) => AddStage($"{nameof(OnRequestStart)}-Kestrel", timestamp);
public void OnRequestStop(DateTime timestamp, string connectionId, string requestId, string httpVersion, string path, string method) => AddStage($"{nameof(OnRequestStop)}-Kestrel", timestamp);
+ public void OnConnectionStop(DateTime timestamp, string connectionId) => AddStage($"{nameof(OnConnectionStop)}-Kestrel", timestamp);
public void OnRedirect(DateTime timestamp, string redirectUri) => AddStage(nameof(OnRedirect), timestamp);
}