From 118b84fa9899409b1c11787633dd8ca704b14b67 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Mon, 11 Oct 2021 22:24:01 +0200 Subject: [PATCH] Change I*MetricsConsumer to a single interface --- .../PrometheusDnsMetrics.cs | 8 +- .../PrometheusForwarderMetrics.cs | 10 +- .../PrometheusKestrelMetrics.cs | 19 ++- .../PrometheusOutboundHttpMetrics.cs | 18 +-- .../PrometheusServiceExtensions.cs | 10 +- .../PrometheusSocketMetrics.cs | 17 ++- .../ForwarderMetricsConsumer.cs | 10 +- .../ReverseProxy.Metrics.Sample/Startup.cs | 2 +- .../EventListenerService.cs | 115 ++++++++++++++--- .../ForwarderEventListenerService.cs | 105 +++------------ .../Forwarder/ForwarderMetrics.cs | 4 +- .../Forwarder/IForwarderMetricsConsumer.cs | 18 --- .../Http/HttpEventListenerService.cs | 105 +++------------ src/TelemetryConsumption/Http/HttpMetrics.cs | 4 +- .../Http/IHttpMetricsConsumer.cs | 18 --- src/TelemetryConsumption/IMetricsConsumer.cs | 18 +++ .../Kestrel/IKestrelMetricsConsumer.cs | 18 --- .../Kestrel/KestrelEventListenerService.cs | 122 ++++-------------- .../Kestrel/KestrelMetrics.cs | 11 +- .../INameResolutionMetricsConsumer.cs | 18 --- .../NameResolutionEventListenerService.cs | 89 ++----------- .../NameResolution/NameResolutionMetrics.cs | 4 +- .../INetSecurityMetricsConsumer.cs | 18 --- .../NetSecurityEventListenerService.cs | 89 ++----------- .../NetSecurity/NetSecurityMetrics.cs | 4 +- .../Sockets/ISocketsMetricsConsumer.cs | 18 --- .../Sockets/SocketsEventListenerService.cs | 102 +++------------ .../Sockets/SocketsMetrics.cs | 4 +- .../WebSocketsEventListenerService.cs | 30 ++--- .../Yarp.Telemetry.Consumption.csproj | 2 - .../TelemetryConsumptionTests.cs | 36 +++--- .../ForwarderMetricsConsumer.cs | 10 +- testassets/ReverseProxy.Code/Startup.cs | 2 +- 33 files changed, 325 insertions(+), 733 deletions(-) delete mode 100644 src/TelemetryConsumption/Forwarder/IForwarderMetricsConsumer.cs delete mode 100644 src/TelemetryConsumption/Http/IHttpMetricsConsumer.cs create mode 100644 src/TelemetryConsumption/IMetricsConsumer.cs delete mode 100644 src/TelemetryConsumption/Kestrel/IKestrelMetricsConsumer.cs delete mode 100644 src/TelemetryConsumption/NameResolution/INameResolutionMetricsConsumer.cs delete mode 100644 src/TelemetryConsumption/NetSecurity/INetSecurityMetricsConsumer.cs delete mode 100644 src/TelemetryConsumption/Sockets/ISocketsMetricsConsumer.cs diff --git a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusDnsMetrics.cs b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusDnsMetrics.cs index fcc2fcee3..b5e56fec4 100644 --- a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusDnsMetrics.cs +++ b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusDnsMetrics.cs @@ -8,7 +8,7 @@ namespace Yarp.Sample { - public sealed class PrometheusDnsMetrics : INameResolutionMetricsConsumer + public sealed class PrometheusDnsMetrics : IMetricsConsumer { private static readonly Counter _dnsLookupsRequested = Metrics.CreateCounter( "yarp_dns_lookups_requested", @@ -20,10 +20,10 @@ public sealed class PrometheusDnsMetrics : INameResolutionMetricsConsumer "Average DNS lookup duration" ); - public void OnNameResolutionMetrics(NameResolutionMetrics oldMetrics, NameResolutionMetrics newMetrics) + public void OnMetrics(NameResolutionMetrics previous, NameResolutionMetrics current) { - _dnsLookupsRequested.IncTo(newMetrics.DnsLookupsRequested); - _averageLookupDuration.Set(newMetrics.AverageLookupDuration.TotalMilliseconds); + _dnsLookupsRequested.IncTo(current.DnsLookupsRequested); + _averageLookupDuration.Set(current.AverageLookupDuration.TotalMilliseconds); } } } diff --git a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusForwarderMetrics.cs b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusForwarderMetrics.cs index aaf3ee87b..3d4cb3754 100644 --- a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusForwarderMetrics.cs +++ b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusForwarderMetrics.cs @@ -6,7 +6,7 @@ namespace Yarp.Sample { - public sealed class PrometheusForwarderMetrics : IForwarderMetricsConsumer + public sealed class PrometheusForwarderMetrics : IMetricsConsumer { private static readonly Counter _requestsStarted = Metrics.CreateCounter( "yarp_proxy_requests_started", @@ -23,11 +23,11 @@ public sealed class PrometheusForwarderMetrics : IForwarderMetricsConsumer "Number of active proxy requests that have started but not yet completed or failed" ); - public void OnForwarderMetrics(ForwarderMetrics oldMetrics, ForwarderMetrics newMetrics) + public void OnMetrics(ForwarderMetrics previous, ForwarderMetrics current) { - _requestsStarted.IncTo(newMetrics.RequestsStarted); - _requestsFailed.IncTo(newMetrics.RequestsFailed); - _CurrentRequests.Set(newMetrics.CurrentRequests); + _requestsStarted.IncTo(current.RequestsStarted); + _requestsFailed.IncTo(current.RequestsFailed); + _CurrentRequests.Set(current.CurrentRequests); } } } diff --git a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusKestrelMetrics.cs b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusKestrelMetrics.cs index 130eb7ec9..a5bdc01f5 100644 --- a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusKestrelMetrics.cs +++ b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusKestrelMetrics.cs @@ -4,13 +4,12 @@ #if NET -using System; using Yarp.Telemetry.Consumption; using Prometheus; namespace Yarp.Sample { - public sealed class PrometheusKestrelMetrics : IKestrelMetricsConsumer + public sealed class PrometheusKestrelMetrics : IMetricsConsumer { private static readonly Counter _totalConnections = Metrics.CreateCounter( "yarp_kestrel_total_connections", @@ -47,15 +46,15 @@ public sealed class PrometheusKestrelMetrics : IKestrelMetricsConsumer "Number of requests on the queue" ); - public void OnKestrelMetrics(KestrelMetrics oldMetrics, KestrelMetrics newMetrics) + public void OnMetrics(KestrelMetrics previous, KestrelMetrics current) { - _totalConnections.IncTo(newMetrics.TotalConnections); - _totalTlsHandshakes.IncTo(newMetrics.TotalTlsHandshakes); - _currentTlsHandshakes.Set(newMetrics.CurrentTlsHandshakes); - _failedTlsHandshakes.IncTo(newMetrics.FailedTlsHandshakes); - _currentConnections.Set(newMetrics.CurrentConnections); - _connectionQueueLength.Set(newMetrics.ConnectionQueueLength); - _requestQueueLength.Set(newMetrics.RequestQueueLength); + _totalConnections.IncTo(current.TotalConnections); + _totalTlsHandshakes.IncTo(current.TotalTlsHandshakes); + _currentTlsHandshakes.Set(current.CurrentTlsHandshakes); + _failedTlsHandshakes.IncTo(current.FailedTlsHandshakes); + _currentConnections.Set(current.CurrentConnections); + _connectionQueueLength.Set(current.ConnectionQueueLength); + _requestQueueLength.Set(current.RequestQueueLength); } } } diff --git a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusOutboundHttpMetrics.cs b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusOutboundHttpMetrics.cs index 382d22fc0..353cf7d44 100644 --- a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusOutboundHttpMetrics.cs +++ b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusOutboundHttpMetrics.cs @@ -12,7 +12,7 @@ namespace Yarp.Sample /// /// Collects outbound http metrics and exposes them using prometheus-net /// - public sealed class PrometheusOutboundHttpMetrics: IHttpMetricsConsumer + public sealed class PrometheusOutboundHttpMetrics : IMetricsConsumer { private static readonly double CUBE_ROOT_10 = Math.Pow(10, (1.0 / 3)); @@ -57,15 +57,15 @@ public sealed class PrometheusOutboundHttpMetrics: IHttpMetricsConsumer Buckets = Histogram.ExponentialBuckets(10, CUBE_ROOT_10, 10) }); - public void OnHttpMetrics(HttpMetrics oldMetrics, HttpMetrics newMetrics) + public void OnMetrics(HttpMetrics previous, HttpMetrics current) { - _outboundRequestsStarted.IncTo(newMetrics.RequestsStarted); - _outboundRequestsFailed.IncTo(newMetrics.RequestsFailed); - _outboundCurrentRequests.Set(newMetrics.CurrentRequests); - _outboundCurrentHttp11Connections.Set(newMetrics.CurrentHttp11Connections); - _outboundCurrentHttp20Connections.Set(newMetrics.CurrentHttp20Connections); - _outboundHttp11RequestQueueDuration.Observe(newMetrics.Http11RequestsQueueDuration.TotalMilliseconds); - _outboundHttp20RequestQueueDuration.Observe(newMetrics.Http20RequestsQueueDuration.TotalMilliseconds); + _outboundRequestsStarted.IncTo(current.RequestsStarted); + _outboundRequestsFailed.IncTo(current.RequestsFailed); + _outboundCurrentRequests.Set(current.CurrentRequests); + _outboundCurrentHttp11Connections.Set(current.CurrentHttp11Connections); + _outboundCurrentHttp20Connections.Set(current.CurrentHttp20Connections); + _outboundHttp11RequestQueueDuration.Observe(current.Http11RequestsQueueDuration.TotalMilliseconds); + _outboundHttp20RequestQueueDuration.Observe(current.Http20RequestsQueueDuration.TotalMilliseconds); } } } diff --git a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusServiceExtensions.cs b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusServiceExtensions.cs index 8602bd35e..b3516925a 100644 --- a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusServiceExtensions.cs +++ b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusServiceExtensions.cs @@ -11,7 +11,7 @@ public static class PrometheusServiceExtensions public static IServiceCollection AddPrometheusForwarderMetrics(this IServiceCollection services) { services.AddTelemetryListeners(); - services.AddSingleton(); + services.AddSingleton, PrometheusForwarderMetrics>(); return services; } @@ -19,28 +19,28 @@ public static IServiceCollection AddPrometheusForwarderMetrics(this IServiceColl public static IServiceCollection AddPrometheusDnsMetrics(this IServiceCollection services) { services.AddTelemetryListeners(); - services.AddSingleton(); + services.AddSingleton, PrometheusDnsMetrics>(); return services; } public static IServiceCollection AddPrometheusKestrelMetrics(this IServiceCollection services) { services.AddTelemetryListeners(); - services.AddSingleton(); + services.AddSingleton, PrometheusKestrelMetrics>(); return services; } public static IServiceCollection AddPrometheusOutboundHttpMetrics(this IServiceCollection services) { services.AddTelemetryListeners(); - services.AddSingleton(); + services.AddSingleton, PrometheusOutboundHttpMetrics>(); return services; } public static IServiceCollection AddPrometheusSocketsMetrics(this IServiceCollection services) { services.AddTelemetryListeners(); - services.AddSingleton(); + services.AddSingleton, PrometheusSocketMetrics>(); return services; } #endif diff --git a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusSocketMetrics.cs b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusSocketMetrics.cs index 758e962e8..3d27cc85c 100644 --- a/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusSocketMetrics.cs +++ b/samples/Prometheus/ReverseProxy.Metrics-Promethius.Sample/PrometheusSocketMetrics.cs @@ -8,8 +8,7 @@ namespace Yarp.Sample { - - public sealed class PrometheusSocketMetrics : ISocketsMetricsConsumer + public sealed class PrometheusSocketMetrics : IMetricsConsumer { private static readonly Counter _outgoingConnectionsEstablished = Metrics.CreateCounter( "yarp_sockets_outgoing_connections_established", @@ -42,14 +41,14 @@ public sealed class PrometheusSocketMetrics : ISocketsMetricsConsumer "Number of datagrams Sent" ); - public void OnSocketsMetrics(SocketsMetrics oldMetrics, SocketsMetrics newMetrics) + public void OnMetrics(SocketsMetrics previous, SocketsMetrics current) { - _outgoingConnectionsEstablished.IncTo(newMetrics.OutgoingConnectionsEstablished); - _incomingConnectionsEstablished.IncTo(newMetrics.IncomingConnectionsEstablished); - _bytesReceived.IncTo(newMetrics.BytesReceived); - _bytesSent.IncTo(newMetrics.BytesSent); - _datagramsReceived.IncTo(newMetrics.DatagramsReceived); - _datagramsSent.IncTo(newMetrics.DatagramsSent); + _outgoingConnectionsEstablished.IncTo(current.OutgoingConnectionsEstablished); + _incomingConnectionsEstablished.IncTo(current.IncomingConnectionsEstablished); + _bytesReceived.IncTo(current.BytesReceived); + _bytesSent.IncTo(current.BytesSent); + _datagramsReceived.IncTo(current.DatagramsReceived); + _datagramsSent.IncTo(current.DatagramsSent); } } } diff --git a/samples/ReverseProxy.Metrics.Sample/ForwarderMetricsConsumer.cs b/samples/ReverseProxy.Metrics.Sample/ForwarderMetricsConsumer.cs index 6a94f8061..4b9df62dd 100644 --- a/samples/ReverseProxy.Metrics.Sample/ForwarderMetricsConsumer.cs +++ b/samples/ReverseProxy.Metrics.Sample/ForwarderMetricsConsumer.cs @@ -6,13 +6,13 @@ namespace Yarp.Sample { - public sealed class ForwarderMetricsConsumer : IForwarderMetricsConsumer + public sealed class ForwarderMetricsConsumer : IMetricsConsumer { - public void OnForwarderMetrics(ForwarderMetrics oldMetrics, ForwarderMetrics newMetrics) + public void OnMetrics(ForwarderMetrics previous, ForwarderMetrics current) { - var elapsed = newMetrics.Timestamp - oldMetrics.Timestamp; - var newRequests = newMetrics.RequestsStarted - oldMetrics.RequestsStarted; - Console.Title = $"Forwarded {newMetrics.RequestsStarted} requests ({newRequests} in the last {(int)elapsed.TotalMilliseconds} ms)"; + var elapsed = current.Timestamp - previous.Timestamp; + var newRequests = current.RequestsStarted - previous.RequestsStarted; + Console.Title = $"Forwarded {current.RequestsStarted} requests ({newRequests} in the last {(int)elapsed.TotalMilliseconds} ms)"; } } } diff --git a/samples/ReverseProxy.Metrics.Sample/Startup.cs b/samples/ReverseProxy.Metrics.Sample/Startup.cs index 0cf587190..8d541caf7 100644 --- a/samples/ReverseProxy.Metrics.Sample/Startup.cs +++ b/samples/ReverseProxy.Metrics.Sample/Startup.cs @@ -36,7 +36,7 @@ public void ConfigureServices(IServiceCollection services) services.AddHttpContextAccessor(); // Interface that collects general metrics about the proxy forwarder - services.AddSingleton(); + services.AddSingleton, ForwarderMetricsConsumer>(); // Registration of a consumer to events for proxy forwarder telemetry services.AddTelemetryConsumer(); diff --git a/src/TelemetryConsumption/EventListenerService.cs b/src/TelemetryConsumption/EventListenerService.cs index 582ad0af4..516e4093f 100644 --- a/src/TelemetryConsumption/EventListenerService.cs +++ b/src/TelemetryConsumption/EventListenerService.cs @@ -12,13 +12,21 @@ namespace Yarp.Telemetry.Consumption { - internal abstract class EventListenerService : EventListener, IHostedService + internal abstract class EventListenerService : EventListener, IHostedService + where TMetrics : class, new() { protected abstract string EventSourceName { get; } + protected abstract int NumberOfMetrics { get; } + protected abstract void OnEvent(TTelemetryConsumer[] consumers, EventWrittenEventArgs eventData); + protected abstract bool TrySaveMetric(TMetrics metrics, string name, double value); - protected readonly ILogger Logger; - protected readonly TMetricsConsumer[]? MetricsConsumers; - protected readonly TTelemetryConsumer[]? TelemetryConsumers; + private readonly ILogger _logger; + private readonly TTelemetryConsumer[]? _telemetryConsumers; + private readonly IMetricsConsumer[]? _metricsConsumers; + + private int _metricsCount; + private TMetrics? _previousMetrics; + private TMetrics? _currentMetrics; private EventSource? _eventSource; private readonly object _syncObject = new(); @@ -27,29 +35,29 @@ internal abstract class EventListenerService logger, IEnumerable telemetryConsumers, - IEnumerable metricsConsumers) + IEnumerable> metricsConsumers) { - Logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _ = telemetryConsumers ?? throw new ArgumentNullException(nameof(telemetryConsumers)); _ = metricsConsumers ?? throw new ArgumentNullException(nameof(metricsConsumers)); - TelemetryConsumers = telemetryConsumers.ToArray(); - MetricsConsumers = metricsConsumers.ToArray(); + _telemetryConsumers = telemetryConsumers.ToArray(); + _metricsConsumers = metricsConsumers.ToArray(); - if (TelemetryConsumers.Any(s => s is null) || metricsConsumers.Any(c => c is null)) + if (_telemetryConsumers.Any(s => s is null) || metricsConsumers.Any(c => c is null)) { throw new ArgumentException("A consumer may not be null", - TelemetryConsumers.Any(s => s is null) ? nameof(telemetryConsumers) : nameof(metricsConsumers)); + _telemetryConsumers.Any(s => s is null) ? nameof(telemetryConsumers) : nameof(metricsConsumers)); } - if (TelemetryConsumers.Length == 0) + if (_telemetryConsumers.Length == 0) { - TelemetryConsumers = null; + _telemetryConsumers = null; } - if (MetricsConsumers.Length == 0) + if (_metricsConsumers.Length == 0) { - MetricsConsumers = null; + _metricsConsumers = null; } lock (_syncObject) @@ -82,8 +90,8 @@ protected override void OnEventSourceCreated(EventSource eventSource) private void EnableEventSource(EventSource eventSource) { - var enableEvents = TelemetryConsumers is not null; - var enableMetrics = MetricsConsumers is not null; + var enableEvents = _telemetryConsumers is not null; + var enableMetrics = _metricsConsumers is not null; if (!enableEvents && !enableMetrics) { @@ -96,6 +104,81 @@ private void EnableEventSource(EventSource eventSource) EnableEvents(eventSource, eventLevel, EventKeywords.None, arguments); } + protected sealed override void OnEventWritten(EventWrittenEventArgs eventData) + { + if (eventData.EventId <= 0) + { + OnNonUserEvent(eventData); + } + else if (_telemetryConsumers is TTelemetryConsumer[] consumers) + { + OnEvent(consumers, eventData); + } + } + + private void OnNonUserEvent(EventWrittenEventArgs eventData) + { + if (eventData.EventId == -1) + { + // Throwing an exception here would crash the process + if (eventData.EventName != "EventCounters" || + eventData.Payload?.Count != 1 || + eventData.Payload[0] is not IDictionary counters || + !counters.TryGetValue("Name", out var nameObject) || + nameObject is not string name || + !(counters.TryGetValue("Mean", out var valueObj) || counters.TryGetValue("Increment", out valueObj)) || + valueObj is not double value) + { + _logger?.LogDebug("Failed to parse EventCounters event from {EventSourceName}", EventSourceName); + return; + } + + var metrics = _currentMetrics ??= new(); + + if (!TrySaveMetric(metrics, name, value)) + { + return; + } + + if (++_metricsCount == NumberOfMetrics) + { + _metricsCount = 0; + + var previous = _previousMetrics; + _previousMetrics = metrics; + _currentMetrics = null; + + if (previous is null) + { + return; + } + + if (_metricsConsumers is IMetricsConsumer[] consumers) + { + foreach (var consumer in consumers) + { + try + { + consumer.OnMetrics(previous, metrics); + } + catch (Exception ex) + { + _logger?.LogError(ex, "Uncaught exception occured while processing metrics for EventSource {EventSourceName}", EventSourceName); + } + } + } + } + } + else if (eventData.EventId == 0) + { + _logger?.LogError("Received an error message from EventSource {EventSourceName}: {Message}", EventSourceName, eventData.Message); + } + else + { + _logger?.LogDebug("Received an unknown event from EventSource {EventSourceName}: {EventId}", EventSourceName, eventData.EventId); + } + } + public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; diff --git a/src/TelemetryConsumption/Forwarder/ForwarderEventListenerService.cs b/src/TelemetryConsumption/Forwarder/ForwarderEventListenerService.cs index 8ea558eb2..427df699a 100644 --- a/src/TelemetryConsumption/Forwarder/ForwarderEventListenerService.cs +++ b/src/TelemetryConsumption/Forwarder/ForwarderEventListenerService.cs @@ -11,38 +11,18 @@ namespace Yarp.Telemetry.Consumption { - internal sealed class ForwarderEventListenerService : EventListenerService + internal sealed class ForwarderEventListenerService : EventListenerService { - private ForwarderMetrics? _previousMetrics; - private ForwarderMetrics _currentMetrics = new(); - private int _eventCountersCount; - protected override string EventSourceName => "Yarp.ReverseProxy"; - public ForwarderEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable metricsConsumers) + protected override int NumberOfMetrics => 4; + + public ForwarderEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable> metricsConsumers) : base(logger, telemetryConsumers, metricsConsumers) { } - protected override void OnEventWritten(EventWrittenEventArgs eventData) + protected override void OnEvent(IForwarderTelemetryConsumer[] consumers, EventWrittenEventArgs eventData) { - const int MinEventId = 1; - const int MaxEventId = 7; - - if (eventData.EventId < MinEventId || eventData.EventId > MaxEventId) - { - if (eventData.EventId == -1) - { - OnEventCounters(eventData); - } - - return; - } - - if (TelemetryConsumers is null) - { - return; - } - #pragma warning disable IDE0007 // Use implicit type // Explicit type here to drop the object? signature of payload elements ReadOnlyCollection payload = eventData.Payload!; @@ -54,7 +34,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) Debug.Assert(eventData.EventName == "ForwarderStart" && payload.Count == 1); { var destinationPrefix = (string)payload[0]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnForwarderStart(eventData.TimeStamp, destinationPrefix); } @@ -65,7 +45,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) Debug.Assert(eventData.EventName == "ForwarderStop" && payload.Count == 1); { var statusCode = (int)payload[0]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnForwarderStop(eventData.TimeStamp, statusCode); } @@ -76,7 +56,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) Debug.Assert(eventData.EventName == "ForwarderFailed" && payload.Count == 1); { var error = (ForwarderError)payload[0]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnForwarderFailed(eventData.TimeStamp, error); } @@ -87,7 +67,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) Debug.Assert(eventData.EventName == "ForwarderStage" && payload.Count == 1); { var proxyStage = (ForwarderStage)payload[0]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnForwarderStage(eventData.TimeStamp, proxyStage); } @@ -102,7 +82,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) var iops = (long)payload[2]; var readTime = new TimeSpan((long)payload[3]); var writeTime = new TimeSpan((long)payload[4]); - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnContentTransferring(eventData.TimeStamp, isRequest, contentLength, iops, readTime, writeTime); } @@ -118,7 +98,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) var readTime = new TimeSpan((long)payload[3]); var writeTime = new TimeSpan((long)payload[4]); var firstReadTime = new TimeSpan((long)payload[5]); - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnContentTransferred(eventData.TimeStamp, isRequest, contentLength, iops, readTime, writeTime, firstReadTime); } @@ -131,7 +111,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) var clusterId = (string)payload[0]; var routeId = (string)payload[1]; var destinationId = (string)payload[2]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnForwarderInvoke(eventData.TimeStamp, clusterId, routeId, destinationId); } @@ -140,76 +120,33 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) } } - private void OnEventCounters(EventWrittenEventArgs eventData) + protected override bool TrySaveMetric(ForwarderMetrics metrics, string name, double value) { - if (MetricsConsumers is null) - { - return; - } - - Debug.Assert(eventData.EventName == "EventCounters" && eventData.Payload!.Count == 1); - var counters = (IDictionary)eventData.Payload[0]!; + var longValue = (long)value; - if (!counters.TryGetValue("Mean", out var valueObj)) - { - valueObj = counters["Increment"]; - } - - var value = (long)(double)valueObj; - var metrics = _currentMetrics; - - switch ((string)counters["Name"]) + switch (name) { case "requests-started": - metrics.RequestsStarted = value; + metrics.RequestsStarted = longValue; break; case "requests-started-rate": - metrics.RequestsStartedRate = value; + metrics.RequestsStartedRate = longValue; break; case "requests-failed": - metrics.RequestsFailed = value; + metrics.RequestsFailed = longValue; break; case "current-requests": - metrics.CurrentRequests = value; + metrics.CurrentRequests = longValue; break; default: - return; + return false; } - const int TotalEventCounters = 4; - - if (++_eventCountersCount == TotalEventCounters) - { - _eventCountersCount = 0; - - metrics.Timestamp = DateTime.UtcNow; - - var previous = _previousMetrics; - _previousMetrics = metrics; - _currentMetrics = new ForwarderMetrics(); - - if (previous is null) - { - return; - } - - try - { - foreach (var consumer in MetricsConsumers) - { - consumer.OnForwarderMetrics(previous, metrics); - } - } - catch (Exception ex) - { - // We can't let an uncaught exception propagate as that would crash the process - Logger.LogError(ex, $"Uncaught exception occured while processing {nameof(ForwarderMetrics)}."); - } - } + return true; } } } diff --git a/src/TelemetryConsumption/Forwarder/ForwarderMetrics.cs b/src/TelemetryConsumption/Forwarder/ForwarderMetrics.cs index d7cff6ef6..00b58a725 100644 --- a/src/TelemetryConsumption/Forwarder/ForwarderMetrics.cs +++ b/src/TelemetryConsumption/Forwarder/ForwarderMetrics.cs @@ -10,6 +10,8 @@ namespace Yarp.Telemetry.Consumption /// public sealed class ForwarderMetrics { + public ForwarderMetrics() => Timestamp = DateTime.UtcNow; + /// /// Timestamp of when this instance was created. /// @@ -34,7 +36,5 @@ public sealed class ForwarderMetrics /// Number of active proxy requests that have started but not yet completed or failed. /// public long CurrentRequests { get; internal set; } - - internal ForwarderMetrics() { } } } diff --git a/src/TelemetryConsumption/Forwarder/IForwarderMetricsConsumer.cs b/src/TelemetryConsumption/Forwarder/IForwarderMetricsConsumer.cs deleted file mode 100644 index fe210e876..000000000 --- a/src/TelemetryConsumption/Forwarder/IForwarderMetricsConsumer.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace Yarp.Telemetry.Consumption -{ - /// - /// A consumer of . - /// - public interface IForwarderMetricsConsumer - { - /// - /// Processes from the last event counter interval. - /// - /// Metrics collected in the previous interval. - /// Metrics collected in the last interval. - void OnForwarderMetrics(ForwarderMetrics oldMetrics, ForwarderMetrics newMetrics); - } -} diff --git a/src/TelemetryConsumption/Http/HttpEventListenerService.cs b/src/TelemetryConsumption/Http/HttpEventListenerService.cs index af59105cd..c2ddafaa1 100644 --- a/src/TelemetryConsumption/Http/HttpEventListenerService.cs +++ b/src/TelemetryConsumption/Http/HttpEventListenerService.cs @@ -11,38 +11,18 @@ namespace Yarp.Telemetry.Consumption { - internal sealed class HttpEventListenerService : EventListenerService + internal sealed class HttpEventListenerService : EventListenerService { - private HttpMetrics? _previousMetrics; - private HttpMetrics _currentMetrics = new(); - private int _eventCountersCount; - protected override string EventSourceName => "System.Net.Http"; - public HttpEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable metricsConsumers) + protected override int NumberOfMetrics => 9; + + public HttpEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable> metricsConsumers) : base(logger, telemetryConsumers, metricsConsumers) { } - protected override void OnEventWritten(EventWrittenEventArgs eventData) + protected override void OnEvent(IHttpTelemetryConsumer[] consumers, EventWrittenEventArgs eventData) { - const int MinEventId = 1; - const int MaxEventId = 12; - - if (eventData.EventId < MinEventId || eventData.EventId > MaxEventId) - { - if (eventData.EventId == -1) - { - OnEventCounters(eventData); - } - - return; - } - - if (TelemetryConsumers is null) - { - return; - } - #pragma warning disable IDE0007 // Use implicit type // Explicit type here to drop the object? signature of payload elements ReadOnlyCollection payload = eventData.Payload!; @@ -60,7 +40,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) var versionMajor = (int)(byte)payload[4]; var versionMinor = (int)(byte)payload[5]; var versionPolicy = (HttpVersionPolicy)payload[6]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestStart(eventData.TimeStamp, scheme, host, port, pathAndQuery, versionMajor, versionMinor, versionPolicy); } @@ -70,7 +50,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) case 2: Debug.Assert(eventData.EventName == "RequestStop" && payload.Count == 0); { - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestStop(eventData.TimeStamp); } @@ -80,7 +60,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) case 3: Debug.Assert(eventData.EventName == "RequestFailed" && payload.Count == 0); { - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestFailed(eventData.TimeStamp); } @@ -92,7 +72,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) { var versionMajor = (int)(byte)payload[0]; var versionMinor = (int)(byte)payload[1]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnConnectionEstablished(eventData.TimeStamp, versionMajor, versionMinor); } @@ -109,7 +89,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) var timeOnQueue = TimeSpan.FromMilliseconds((double)payload[0]); var versionMajor = (int)(byte)payload[1]; var versionMinor = (int)(byte)payload[2]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestLeftQueue(eventData.TimeStamp, timeOnQueue, versionMajor, versionMinor); } @@ -119,7 +99,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) case 7: Debug.Assert(eventData.EventName == "RequestHeadersStart" && payload.Count == 0); { - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestHeadersStart(eventData.TimeStamp); } @@ -129,7 +109,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) case 8: Debug.Assert(eventData.EventName == "RequestHeadersStop" && payload.Count == 0); { - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestHeadersStop(eventData.TimeStamp); } @@ -139,7 +119,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) case 9: Debug.Assert(eventData.EventName == "RequestContentStart" && payload.Count == 0); { - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestContentStart(eventData.TimeStamp); } @@ -150,7 +130,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) Debug.Assert(eventData.EventName == "RequestContentStop" && payload.Count == 1); { var contentLength = (long)payload[0]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestContentStop(eventData.TimeStamp, contentLength); } @@ -160,7 +140,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) case 11: Debug.Assert(eventData.EventName == "ResponseHeadersStart" && payload.Count == 0); { - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnResponseHeadersStart(eventData.TimeStamp); } @@ -170,7 +150,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) case 12: Debug.Assert(eventData.EventName == "ResponseHeadersStop" && payload.Count == 0); { - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnResponseHeadersStop(eventData.TimeStamp); } @@ -179,25 +159,9 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) } } - private void OnEventCounters(EventWrittenEventArgs eventData) + protected override bool TrySaveMetric(HttpMetrics metrics, string name, double value) { - if (MetricsConsumers is null) - { - return; - } - - Debug.Assert(eventData.EventName == "EventCounters" && eventData.Payload!.Count == 1); - var counters = (IDictionary)eventData.Payload[0]!; - - if (!counters.TryGetValue("Mean", out var valueObj)) - { - valueObj = counters["Increment"]; - } - - var value = (double)valueObj; - var metrics = _currentMetrics; - - switch ((string)counters["Name"]) + switch (name) { case "requests-started": metrics.RequestsStarted = (long)value; @@ -236,39 +200,10 @@ private void OnEventCounters(EventWrittenEventArgs eventData) break; default: - return; + return false; } - const int TotalEventCounters = 9; - - if (++_eventCountersCount == TotalEventCounters) - { - _eventCountersCount = 0; - - metrics.Timestamp = DateTime.UtcNow; - - var previous = _previousMetrics; - _previousMetrics = metrics; - _currentMetrics = new HttpMetrics(); - - if (previous is null) - { - return; - } - - try - { - foreach (var consumer in MetricsConsumers) - { - consumer.OnHttpMetrics(previous, metrics); - } - } - catch (Exception ex) - { - // We can't let an uncaught exception propagate as that would crash the process - Logger.LogError(ex, $"Uncaught exception occured while processing {nameof(HttpMetrics)}."); - } - } + return true; } } } diff --git a/src/TelemetryConsumption/Http/HttpMetrics.cs b/src/TelemetryConsumption/Http/HttpMetrics.cs index 0a6a4d16c..6adc0ab8d 100644 --- a/src/TelemetryConsumption/Http/HttpMetrics.cs +++ b/src/TelemetryConsumption/Http/HttpMetrics.cs @@ -10,6 +10,8 @@ namespace Yarp.Telemetry.Consumption /// public sealed class HttpMetrics { + public HttpMetrics() => Timestamp = DateTime.UtcNow; + /// /// Timestamp of when this instance was created. /// @@ -59,7 +61,5 @@ public sealed class HttpMetrics /// Average time spent on queue for HTTP 2.0 requests that hit the MAX_CONCURRENT_STREAMS limit on the connection in the last metrics interval. /// public TimeSpan Http20RequestsQueueDuration { get; internal set; } - - internal HttpMetrics() { } } } diff --git a/src/TelemetryConsumption/Http/IHttpMetricsConsumer.cs b/src/TelemetryConsumption/Http/IHttpMetricsConsumer.cs deleted file mode 100644 index 786b5dd4f..000000000 --- a/src/TelemetryConsumption/Http/IHttpMetricsConsumer.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace Yarp.Telemetry.Consumption -{ - /// - /// A consumer of . - /// - public interface IHttpMetricsConsumer - { - /// - /// Processes from the last event counter interval. - /// - /// Metrics collected in the previous interval. - /// Metrics collected in the last interval. - void OnHttpMetrics(HttpMetrics oldMetrics, HttpMetrics newMetrics); - } -} diff --git a/src/TelemetryConsumption/IMetricsConsumer.cs b/src/TelemetryConsumption/IMetricsConsumer.cs new file mode 100644 index 000000000..363270aa0 --- /dev/null +++ b/src/TelemetryConsumption/IMetricsConsumer.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Yarp.Telemetry.Consumption +{ + /// + /// A consumer of . + /// + public interface IMetricsConsumer + { + /// + /// Processes from the last event counter interval. + /// + /// collected in the previous interval. + /// collected in the last interval. + void OnMetrics(TMetrics previous, TMetrics current); + } +} diff --git a/src/TelemetryConsumption/Kestrel/IKestrelMetricsConsumer.cs b/src/TelemetryConsumption/Kestrel/IKestrelMetricsConsumer.cs deleted file mode 100644 index e1ce68ee9..000000000 --- a/src/TelemetryConsumption/Kestrel/IKestrelMetricsConsumer.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace Yarp.Telemetry.Consumption -{ - /// - /// A consumer of . - /// - public interface IKestrelMetricsConsumer - { - /// - /// Processes from the last event counter interval. - /// - /// Metrics collected in the previous interval. - /// Metrics collected in the last interval. - void OnKestrelMetrics(KestrelMetrics oldMetrics, KestrelMetrics newMetrics); - } -} diff --git a/src/TelemetryConsumption/Kestrel/KestrelEventListenerService.cs b/src/TelemetryConsumption/Kestrel/KestrelEventListenerService.cs index 09cc9bba7..133ef53d5 100644 --- a/src/TelemetryConsumption/Kestrel/KestrelEventListenerService.cs +++ b/src/TelemetryConsumption/Kestrel/KestrelEventListenerService.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; @@ -10,46 +9,18 @@ namespace Yarp.Telemetry.Consumption { -#if !NET - internal interface IKestrelMetricsConsumer { } -#endif - - internal sealed class KestrelEventListenerService : EventListenerService + internal sealed class KestrelEventListenerService : EventListenerService { -#if NET - private KestrelMetrics? _previousMetrics; - private KestrelMetrics _currentMetrics = new(); - private int _eventCountersCount; -#endif - protected override string EventSourceName => "Microsoft-AspNetCore-Server-Kestrel"; - public KestrelEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable metricsConsumers) + protected override int NumberOfMetrics => 10; + + public KestrelEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable> metricsConsumers) : base(logger, telemetryConsumers, metricsConsumers) { } - protected override void OnEventWritten(EventWrittenEventArgs eventData) + protected override void OnEvent(IKestrelTelemetryConsumer[] consumers, EventWrittenEventArgs eventData) { - const int MinEventId = 3; - const int MaxEventId = 4; - - if (eventData.EventId < MinEventId || eventData.EventId > MaxEventId) - { -#if NET - if (eventData.EventId == -1) - { - OnEventCounters(eventData); - } -#endif - - return; - } - - if (TelemetryConsumers is null) - { - return; - } - #pragma warning disable IDE0007 // Use implicit type // Explicit type here to drop the object? signature of payload elements ReadOnlyCollection payload = eventData.Payload!; @@ -66,7 +37,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) var httpVersion = (string)payload[2]; var path = (string)payload[3]; var method = (string)payload[4]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestStart(eventData.TimeStamp, connectionId, requestId, httpVersion, path, method); } @@ -81,7 +52,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) var httpVersion = (string)payload[2]; var path = (string)payload[3]; var method = (string)payload[4]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestStop(eventData.TimeStamp, connectionId, requestId, httpVersion, path, method); } @@ -96,7 +67,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) { var connectionId = (string)payload[0]; var requestId = (string)payload[1]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestStart(eventData.TimeStamp, connectionId, requestId); } @@ -108,7 +79,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) { var connectionId = (string)payload[0]; var requestId = (string)payload[1]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnRequestStop(eventData.TimeStamp, connectionId, requestId); } @@ -118,102 +89,57 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) #endif } -#if NET - private void OnEventCounters(EventWrittenEventArgs eventData) + protected override bool TrySaveMetric(KestrelMetrics metrics, string name, double value) { - if (MetricsConsumers is null) - { - return; - } - - Debug.Assert(eventData.EventName == "EventCounters" && eventData.Payload!.Count == 1); - var counters = (IDictionary)eventData.Payload[0]!; + var longValue = (long)value; - if (!counters.TryGetValue("Mean", out var valueObj)) - { - valueObj = counters["Increment"]; - } - - var value = (long)(double)valueObj; - var metrics = _currentMetrics; - - switch ((string)counters["Name"]) + switch (name) { case "connections-per-second": - metrics.ConnectionRate = value; + metrics.ConnectionRate = longValue; break; case "total-connections": - metrics.TotalConnections = value; + metrics.TotalConnections = longValue; break; case "tls-handshakes-per-second": - metrics.TlsHandshakeRate = value; + metrics.TlsHandshakeRate = longValue; break; case "total-tls-handshakes": - metrics.TotalTlsHandshakes = value; + metrics.TotalTlsHandshakes = longValue; break; case "current-tls-handshakes": - metrics.CurrentTlsHandshakes = value; + metrics.CurrentTlsHandshakes = longValue; break; case "failed-tls-handshakes": - metrics.FailedTlsHandshakes = value; + metrics.FailedTlsHandshakes = longValue; break; case "current-connections": - metrics.CurrentConnections = value; + metrics.CurrentConnections = longValue; break; case "connection-queue-length": - metrics.ConnectionQueueLength = value; + metrics.ConnectionQueueLength = longValue; break; case "request-queue-length": - metrics.RequestQueueLength = value; + metrics.RequestQueueLength = longValue; break; case "current-upgraded-requests": - metrics.CurrentUpgradedRequests = value; + metrics.CurrentUpgradedRequests = longValue; break; default: - return; + return false; } - const int TotalEventCounters = 10; - - if (++_eventCountersCount == TotalEventCounters) - { - _eventCountersCount = 0; - - metrics.Timestamp = DateTime.UtcNow; - - var previous = _previousMetrics; - _previousMetrics = metrics; - _currentMetrics = new KestrelMetrics(); - - if (previous is null) - { - return; - } - - try - { - foreach (var consumer in MetricsConsumers) - { - consumer.OnKestrelMetrics(previous, metrics); - } - } - catch (Exception ex) - { - // We can't let an uncaught exception propagate as that would crash the process - Logger.LogError(ex, $"Uncaught exception occured while processing {nameof(KestrelMetrics)}."); - } - } + return true; } -#endif } } diff --git a/src/TelemetryConsumption/Kestrel/KestrelMetrics.cs b/src/TelemetryConsumption/Kestrel/KestrelMetrics.cs index c8df37463..394bb86a7 100644 --- a/src/TelemetryConsumption/Kestrel/KestrelMetrics.cs +++ b/src/TelemetryConsumption/Kestrel/KestrelMetrics.cs @@ -8,8 +8,15 @@ namespace Yarp.Telemetry.Consumption /// /// Represents metrics reported by the Microsoft-AspNetCore-Server-Kestrel event counters. /// - public sealed class KestrelMetrics +#if NET + public +#else + internal +#endif + sealed class KestrelMetrics { + public KestrelMetrics() => Timestamp = DateTime.UtcNow; + /// /// Timestamp of when this instance was created. /// @@ -64,7 +71,5 @@ public sealed class KestrelMetrics /// Number of currently upgraded requests (number of webSocket connections). /// public long CurrentUpgradedRequests { get; internal set; } - - internal KestrelMetrics() { } } } diff --git a/src/TelemetryConsumption/NameResolution/INameResolutionMetricsConsumer.cs b/src/TelemetryConsumption/NameResolution/INameResolutionMetricsConsumer.cs deleted file mode 100644 index 3e047b9a0..000000000 --- a/src/TelemetryConsumption/NameResolution/INameResolutionMetricsConsumer.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace Yarp.Telemetry.Consumption -{ - /// - /// A consumer of . - /// - public interface INameResolutionMetricsConsumer - { - /// - /// Processes from the last event counter interval. - /// - /// Metrics collected in the previous interval. - /// Metrics collected in the last interval. - void OnNameResolutionMetrics(NameResolutionMetrics oldMetrics, NameResolutionMetrics newMetrics); - } -} diff --git a/src/TelemetryConsumption/NameResolution/NameResolutionEventListenerService.cs b/src/TelemetryConsumption/NameResolution/NameResolutionEventListenerService.cs index a6628970a..c381044b2 100644 --- a/src/TelemetryConsumption/NameResolution/NameResolutionEventListenerService.cs +++ b/src/TelemetryConsumption/NameResolution/NameResolutionEventListenerService.cs @@ -10,38 +10,18 @@ namespace Yarp.Telemetry.Consumption { - internal sealed class NameResolutionEventListenerService : EventListenerService + internal sealed class NameResolutionEventListenerService : EventListenerService { - private NameResolutionMetrics? _previousMetrics; - private NameResolutionMetrics _currentMetrics = new(); - private int _eventCountersCount; - protected override string EventSourceName => "System.Net.NameResolution"; - public NameResolutionEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable metricsConsumers) + protected override int NumberOfMetrics => 2; + + public NameResolutionEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable> metricsConsumers) : base(logger, telemetryConsumers, metricsConsumers) { } - protected override void OnEventWritten(EventWrittenEventArgs eventData) + protected override void OnEvent(INameResolutionTelemetryConsumer[] consumers, EventWrittenEventArgs eventData) { - const int MinEventId = 1; - const int MaxEventId = 3; - - if (eventData.EventId < MinEventId || eventData.EventId > MaxEventId) - { - if (eventData.EventId == -1) - { - OnEventCounters(eventData); - } - - return; - } - - if (TelemetryConsumers is null) - { - return; - } - #pragma warning disable IDE0007 // Use implicit type // Explicit type here to drop the object? signature of payload elements ReadOnlyCollection payload = eventData.Payload!; @@ -53,7 +33,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) Debug.Assert(eventData.EventName == "ResolutionStart" && payload.Count == 1); { var hostNameOrAddress = (string)payload[0]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnResolutionStart(eventData.TimeStamp, hostNameOrAddress); } @@ -63,7 +43,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) case 2: Debug.Assert(eventData.EventName == "ResolutionStop" && payload.Count == 0); { - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnResolutionStop(eventData.TimeStamp); } @@ -73,7 +53,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) case 3: Debug.Assert(eventData.EventName == "ResolutionFailed" && payload.Count == 0); { - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnResolutionFailed(eventData.TimeStamp); } @@ -82,25 +62,9 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) } } - private void OnEventCounters(EventWrittenEventArgs eventData) + protected override bool TrySaveMetric(NameResolutionMetrics metrics, string name, double value) { - if (MetricsConsumers is null) - { - return; - } - - Debug.Assert(eventData.EventName == "EventCounters" && eventData.Payload!.Count == 1); - var counters = (IDictionary)eventData.Payload[0]!; - - if (!counters.TryGetValue("Mean", out var valueObj)) - { - valueObj = counters["Increment"]; - } - - var value = (double)valueObj; - var metrics = _currentMetrics; - - switch ((string)counters["Name"]) + switch (name) { case "dns-lookups-requested": metrics.DnsLookupsRequested = (long)value; @@ -111,39 +75,10 @@ private void OnEventCounters(EventWrittenEventArgs eventData) break; default: - return; + return false; } - const int TotalEventCounters = 2; - - if (++_eventCountersCount == TotalEventCounters) - { - _eventCountersCount = 0; - - metrics.Timestamp = DateTime.UtcNow; - - var previous = _previousMetrics; - _previousMetrics = metrics; - _currentMetrics = new NameResolutionMetrics(); - - if (previous is null) - { - return; - } - - try - { - foreach (var consumer in MetricsConsumers) - { - consumer.OnNameResolutionMetrics(previous, metrics); - } - } - catch (Exception ex) - { - // We can't let an uncaught exception propagate as that would crash the process - Logger.LogError(ex, $"Uncaught exception occured while processing {nameof(NameResolutionMetrics)}."); - } - } + return true; } } } diff --git a/src/TelemetryConsumption/NameResolution/NameResolutionMetrics.cs b/src/TelemetryConsumption/NameResolution/NameResolutionMetrics.cs index c647bdd79..fb3dfc6a5 100644 --- a/src/TelemetryConsumption/NameResolution/NameResolutionMetrics.cs +++ b/src/TelemetryConsumption/NameResolution/NameResolutionMetrics.cs @@ -10,6 +10,8 @@ namespace Yarp.Telemetry.Consumption /// public sealed class NameResolutionMetrics { + public NameResolutionMetrics() => Timestamp = DateTime.UtcNow; + /// /// Timestamp of when this instance was created. /// @@ -24,7 +26,5 @@ public sealed class NameResolutionMetrics /// Average DNS lookup duration in the last metrics interval. /// public TimeSpan AverageLookupDuration { get; internal set; } - - internal NameResolutionMetrics() { } } } diff --git a/src/TelemetryConsumption/NetSecurity/INetSecurityMetricsConsumer.cs b/src/TelemetryConsumption/NetSecurity/INetSecurityMetricsConsumer.cs deleted file mode 100644 index 70c4a0e2a..000000000 --- a/src/TelemetryConsumption/NetSecurity/INetSecurityMetricsConsumer.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace Yarp.Telemetry.Consumption -{ - /// - /// A consumer of . - /// - public interface INetSecurityMetricsConsumer - { - /// - /// Processes from the last event counter interval. - /// - /// Metrics collected in the previous interval. - /// Metrics collected in the last interval. - void OnNetSecurityMetrics(NetSecurityMetrics oldMetrics, NetSecurityMetrics newMetrics); - } -} diff --git a/src/TelemetryConsumption/NetSecurity/NetSecurityEventListenerService.cs b/src/TelemetryConsumption/NetSecurity/NetSecurityEventListenerService.cs index 610dae449..5fdc9c787 100644 --- a/src/TelemetryConsumption/NetSecurity/NetSecurityEventListenerService.cs +++ b/src/TelemetryConsumption/NetSecurity/NetSecurityEventListenerService.cs @@ -11,38 +11,18 @@ namespace Yarp.Telemetry.Consumption { - internal sealed class NetSecurityEventListenerService : EventListenerService + internal sealed class NetSecurityEventListenerService : EventListenerService { - private NetSecurityMetrics? _previousMetrics; - private NetSecurityMetrics _currentMetrics = new(); - private int _eventCountersCount; - protected override string EventSourceName => "System.Net.Security"; - public NetSecurityEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable metricsConsumers) + protected override int NumberOfMetrics => 14; + + public NetSecurityEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable> metricsConsumers) : base(logger, telemetryConsumers, metricsConsumers) { } - protected override void OnEventWritten(EventWrittenEventArgs eventData) + protected override void OnEvent(INetSecurityTelemetryConsumer[] consumers, EventWrittenEventArgs eventData) { - const int MinEventId = 1; - const int MaxEventId = 3; - - if (eventData.EventId < MinEventId || eventData.EventId > MaxEventId) - { - if (eventData.EventId == -1) - { - OnEventCounters(eventData); - } - - return; - } - - if (TelemetryConsumers is null) - { - return; - } - #pragma warning disable IDE0007 // Use implicit type // Explicit type here to drop the object? signature of payload elements ReadOnlyCollection payload = eventData.Payload!; @@ -55,7 +35,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) { var isServer = (bool)payload[0]; var targetHost = (string)payload[1]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnHandshakeStart(eventData.TimeStamp, isServer, targetHost); } @@ -66,7 +46,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) Debug.Assert(eventData.EventName == "HandshakeStop" && payload.Count == 1); { var protocol = (SslProtocols)payload[0]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnHandshakeStop(eventData.TimeStamp, protocol); } @@ -79,7 +59,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) var isServer = (bool)payload[0]; var elapsed = TimeSpan.FromMilliseconds((double)payload[1]); var exceptionMessage = (string)payload[2]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnHandshakeFailed(eventData.TimeStamp, isServer, elapsed, exceptionMessage); } @@ -88,25 +68,9 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) } } - private void OnEventCounters(EventWrittenEventArgs eventData) + protected override bool TrySaveMetric(NetSecurityMetrics metrics, string name, double value) { - if (MetricsConsumers is null) - { - return; - } - - Debug.Assert(eventData.EventName == "EventCounters" && eventData.Payload!.Count == 1); - var counters = (IDictionary)eventData.Payload[0]!; - - if (!counters.TryGetValue("Mean", out var valueObj)) - { - valueObj = counters["Increment"]; - } - - var value = (double)valueObj; - var metrics = _currentMetrics; - - switch ((string)counters["Name"]) + switch (name) { case "tls-handshake-rate": metrics.TlsHandshakeRate = (long)value; @@ -165,39 +129,10 @@ private void OnEventCounters(EventWrittenEventArgs eventData) break; default: - return; + return false; } - const int TotalEventCounters = 14; - - if (++_eventCountersCount == TotalEventCounters) - { - _eventCountersCount = 0; - - metrics.Timestamp = DateTime.UtcNow; - - var previous = _previousMetrics; - _previousMetrics = metrics; - _currentMetrics = new NetSecurityMetrics(); - - if (previous is null) - { - return; - } - - try - { - foreach (var consumer in MetricsConsumers) - { - consumer.OnNetSecurityMetrics(previous, metrics); - } - } - catch (Exception ex) - { - // We can't let an uncaught exception propagate as that would crash the process - Logger.LogError(ex, $"Uncaught exception occured while processing {nameof(NetSecurityMetrics)}."); - } - } + return true; } } } diff --git a/src/TelemetryConsumption/NetSecurity/NetSecurityMetrics.cs b/src/TelemetryConsumption/NetSecurity/NetSecurityMetrics.cs index 23cb09765..a3e064679 100644 --- a/src/TelemetryConsumption/NetSecurity/NetSecurityMetrics.cs +++ b/src/TelemetryConsumption/NetSecurity/NetSecurityMetrics.cs @@ -10,6 +10,8 @@ namespace Yarp.Telemetry.Consumption /// public sealed class NetSecurityMetrics { + public NetSecurityMetrics() => Timestamp = DateTime.UtcNow; + /// /// Timestamp of when this instance was created. /// @@ -84,7 +86,5 @@ public sealed class NetSecurityMetrics /// Average duration of all TLS 1.3 handshakes completed in the last metrics interval. /// public TimeSpan Tls13HandshakeDuration { get; internal set; } - - internal NetSecurityMetrics() { } } } diff --git a/src/TelemetryConsumption/Sockets/ISocketsMetricsConsumer.cs b/src/TelemetryConsumption/Sockets/ISocketsMetricsConsumer.cs deleted file mode 100644 index 886847328..000000000 --- a/src/TelemetryConsumption/Sockets/ISocketsMetricsConsumer.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace Yarp.Telemetry.Consumption -{ - /// - /// A consumer of . - /// - public interface ISocketsMetricsConsumer - { - /// - /// Processes from the last event counter interval. - /// - /// Metrics collected in the previous interval. - /// Metrics collected in the last interval. - void OnSocketsMetrics(SocketsMetrics oldMetrics, SocketsMetrics newMetrics); - } -} diff --git a/src/TelemetryConsumption/Sockets/SocketsEventListenerService.cs b/src/TelemetryConsumption/Sockets/SocketsEventListenerService.cs index ccf13719a..4b7b7575e 100644 --- a/src/TelemetryConsumption/Sockets/SocketsEventListenerService.cs +++ b/src/TelemetryConsumption/Sockets/SocketsEventListenerService.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; @@ -11,38 +10,18 @@ namespace Yarp.Telemetry.Consumption { - internal sealed class SocketsEventListenerService : EventListenerService + internal sealed class SocketsEventListenerService : EventListenerService { - private SocketsMetrics? _previousMetrics; - private SocketsMetrics _currentMetrics = new(); - private int _eventCountersCount; - protected override string EventSourceName => "System.Net.Sockets"; - public SocketsEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable metricsConsumers) + protected override int NumberOfMetrics => 6; + + public SocketsEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable> metricsConsumers) : base(logger, telemetryConsumers, metricsConsumers) { } - protected override void OnEventWritten(EventWrittenEventArgs eventData) + protected override void OnEvent(ISocketsTelemetryConsumer[] consumers, EventWrittenEventArgs eventData) { - const int MinEventId = 1; - const int MaxEventId = 3; - - if (eventData.EventId < MinEventId || eventData.EventId > MaxEventId) - { - if (eventData.EventId == -1) - { - OnEventCounters(eventData); - } - - return; - } - - if (TelemetryConsumers is null) - { - return; - } - #pragma warning disable IDE0007 // Use implicit type // Explicit type here to drop the object? signature of payload elements ReadOnlyCollection payload = eventData.Payload!; @@ -54,7 +33,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) Debug.Assert(eventData.EventName == "ConnectStart" && payload.Count == 1); { var address = (string)payload[0]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnConnectStart(eventData.TimeStamp, address); } @@ -64,7 +43,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) case 2: Debug.Assert(eventData.EventName == "ConnectStop" && payload.Count == 0); { - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnConnectStop(eventData.TimeStamp); } @@ -76,7 +55,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) { var error = (SocketError)payload[0]; var exceptionMessage = (string)payload[1]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnConnectFailed(eventData.TimeStamp, error, exceptionMessage); } @@ -85,84 +64,41 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) } } - private void OnEventCounters(EventWrittenEventArgs eventData) + protected override bool TrySaveMetric(SocketsMetrics metrics, string name, double value) { - if (MetricsConsumers is null) - { - return; - } - - Debug.Assert(eventData.EventName == "EventCounters" && eventData.Payload!.Count == 1); - var counters = (IDictionary)eventData.Payload[0]!; + var longValue = (long)value; - if (!counters.TryGetValue("Mean", out var valueObj)) - { - valueObj = counters["Increment"]; - } - - var value = (long)(double)valueObj; - var metrics = _currentMetrics; - - switch ((string)counters["Name"]) + switch (name) { case "outgoing-connections-established": - metrics.OutgoingConnectionsEstablished = value; + metrics.OutgoingConnectionsEstablished = longValue; break; case "incoming-connections-established": - metrics.IncomingConnectionsEstablished = value; + metrics.IncomingConnectionsEstablished = longValue; break; case "bytes-received": - metrics.BytesReceived = value; + metrics.BytesReceived = longValue; break; case "bytes-sent": - metrics.BytesSent = value; + metrics.BytesSent = longValue; break; case "datagrams-received": - metrics.DatagramsReceived = value; + metrics.DatagramsReceived = longValue; break; case "datagrams-sent": - metrics.DatagramsSent = value; + metrics.DatagramsSent = longValue; break; default: - return; + return false; } - const int TotalEventCounters = 6; - - if (++_eventCountersCount == TotalEventCounters) - { - _eventCountersCount = 0; - - metrics.Timestamp = DateTime.UtcNow; - - var previous = _previousMetrics; - _previousMetrics = metrics; - _currentMetrics = new SocketsMetrics(); - - if (previous is null) - { - return; - } - - try - { - foreach (var consumer in MetricsConsumers) - { - consumer.OnSocketsMetrics(previous, metrics); - } - } - catch (Exception ex) - { - // We can't let an uncaught exception propagate as that would crash the process - Logger.LogError(ex, $"Uncaught exception occured while processing {nameof(SocketsMetrics)}."); - } - } + return true; } } } diff --git a/src/TelemetryConsumption/Sockets/SocketsMetrics.cs b/src/TelemetryConsumption/Sockets/SocketsMetrics.cs index 64bd76e48..27e69daa1 100644 --- a/src/TelemetryConsumption/Sockets/SocketsMetrics.cs +++ b/src/TelemetryConsumption/Sockets/SocketsMetrics.cs @@ -10,6 +10,8 @@ namespace Yarp.Telemetry.Consumption /// public sealed class SocketsMetrics { + public SocketsMetrics() => Timestamp = DateTime.UtcNow; + /// /// Timestamp of when this instance was created. /// @@ -44,7 +46,5 @@ public sealed class SocketsMetrics /// Number of datagrams sent since telemetry was enabled. /// public long DatagramsSent { get; internal set; } - - internal SocketsMetrics() { } } } diff --git a/src/TelemetryConsumption/WebSockets/WebSocketsEventListenerService.cs b/src/TelemetryConsumption/WebSockets/WebSocketsEventListenerService.cs index fc54c0ee9..ee2835d95 100644 --- a/src/TelemetryConsumption/WebSockets/WebSocketsEventListenerService.cs +++ b/src/TelemetryConsumption/WebSockets/WebSocketsEventListenerService.cs @@ -10,31 +10,20 @@ namespace Yarp.Telemetry.Consumption { - internal interface IWebSocketsMetricsConsumer { } + internal sealed class WebSocketsMetrics { } - internal sealed class WebSocketsEventListenerService : EventListenerService + internal sealed class WebSocketsEventListenerService : EventListenerService { protected override string EventSourceName => "Yarp.ReverseProxy.WebSockets"; - public WebSocketsEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable metricsConsumers) + protected override int NumberOfMetrics => 0; + + public WebSocketsEventListenerService(ILogger logger, IEnumerable telemetryConsumers, IEnumerable> metricsConsumers) : base(logger, telemetryConsumers, metricsConsumers) { } - protected override void OnEventWritten(EventWrittenEventArgs eventData) + protected override void OnEvent(IWebSocketsTelemetryConsumer[] consumers, EventWrittenEventArgs eventData) { - const int MinEventId = 1; - const int MaxEventId = 1; - - if (eventData.EventId < MinEventId || eventData.EventId > MaxEventId) - { - return; - } - - if (TelemetryConsumers is null) - { - return; - } - #pragma warning disable IDE0007 // Use implicit type // Explicit type here to drop the object? signature of payload elements ReadOnlyCollection payload = eventData.Payload!; @@ -49,7 +38,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) var closeReason = (WebSocketCloseReason)payload[1]; var messagesRead = (long)payload[2]; var messagesWritten = (long)payload[3]; - foreach (var consumer in TelemetryConsumers) + foreach (var consumer in consumers) { consumer.OnWebSocketClosed(eventData.TimeStamp, establishedTime, closeReason, messagesRead, messagesWritten); } @@ -57,5 +46,10 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) break; } } + + protected override bool TrySaveMetric(WebSocketsMetrics metrics, string name, double value) + { + return false; + } } } diff --git a/src/TelemetryConsumption/Yarp.Telemetry.Consumption.csproj b/src/TelemetryConsumption/Yarp.Telemetry.Consumption.csproj index 1a7dee885..112da42a6 100644 --- a/src/TelemetryConsumption/Yarp.Telemetry.Consumption.csproj +++ b/src/TelemetryConsumption/Yarp.Telemetry.Consumption.csproj @@ -22,8 +22,6 @@ - - diff --git a/test/ReverseProxy.FunctionalTests/TelemetryConsumptionTests.cs b/test/ReverseProxy.FunctionalTests/TelemetryConsumptionTests.cs index e452e707a..5f60b7377 100644 --- a/test/ReverseProxy.FunctionalTests/TelemetryConsumptionTests.cs +++ b/test/ReverseProxy.FunctionalTests/TelemetryConsumptionTests.cs @@ -268,13 +268,13 @@ public async Task MetricsConsumptionWorks() { var services = proxyBuilder.Services; - services.AddSingleton(consumer); + services.AddSingleton>(consumer); #if NET - services.AddSingleton(consumer); - services.AddSingleton(consumer); - services.AddSingleton(consumer); - services.AddSingleton(consumer); - services.AddSingleton(consumer); + services.AddSingleton>(consumer); + services.AddSingleton>(consumer); + services.AddSingleton>(consumer); + services.AddSingleton>(consumer); + services.AddSingleton>(consumer); #endif services.AddTelemetryListeners(); @@ -337,14 +337,14 @@ static async Task WaitAsync(Func condition, string name) } private sealed class MetricsConsumer : - IForwarderMetricsConsumer + IMetricsConsumer #if NET , - IKestrelMetricsConsumer, - IHttpMetricsConsumer, - INameResolutionMetricsConsumer, - INetSecurityMetricsConsumer, - ISocketsMetricsConsumer + IMetricsConsumer, + IMetricsConsumer, + IMetricsConsumer, + IMetricsConsumer, + IMetricsConsumer #endif { public readonly ConcurrentQueue ProxyMetrics = new ConcurrentQueue(); @@ -356,13 +356,13 @@ private sealed class MetricsConsumer : public readonly ConcurrentQueue NameResolutionMetrics = new(); #endif - public void OnForwarderMetrics(ForwarderMetrics oldMetrics, ForwarderMetrics newMetrics) => ProxyMetrics.Enqueue(newMetrics); + public void OnMetrics(ForwarderMetrics previous, ForwarderMetrics current) => ProxyMetrics.Enqueue(current); #if NET - public void OnKestrelMetrics(KestrelMetrics oldMetrics, KestrelMetrics newMetrics) => KestrelMetrics.Enqueue(newMetrics); - public void OnSocketsMetrics(SocketsMetrics oldMetrics, SocketsMetrics newMetrics) => SocketsMetrics.Enqueue(newMetrics); - public void OnNetSecurityMetrics(NetSecurityMetrics oldMetrics, NetSecurityMetrics newMetrics) => NetSecurityMetrics.Enqueue(newMetrics); - public void OnNameResolutionMetrics(NameResolutionMetrics oldMetrics, NameResolutionMetrics newMetrics) => NameResolutionMetrics.Enqueue(newMetrics); - public void OnHttpMetrics(HttpMetrics oldMetrics, HttpMetrics newMetrics) => HttpMetrics.Enqueue(newMetrics); + public void OnMetrics(KestrelMetrics previous, KestrelMetrics current) => KestrelMetrics.Enqueue(current); + public void OnMetrics(SocketsMetrics previous, SocketsMetrics current) => SocketsMetrics.Enqueue(current); + public void OnMetrics(NetSecurityMetrics previous, NetSecurityMetrics current) => NetSecurityMetrics.Enqueue(current); + public void OnMetrics(NameResolutionMetrics previous, NameResolutionMetrics current) => NameResolutionMetrics.Enqueue(current); + public void OnMetrics(HttpMetrics previous, HttpMetrics current) => HttpMetrics.Enqueue(current); #endif } } diff --git a/testassets/ReverseProxy.Code/ForwarderMetricsConsumer.cs b/testassets/ReverseProxy.Code/ForwarderMetricsConsumer.cs index 242ef3fdd..acc4cc413 100644 --- a/testassets/ReverseProxy.Code/ForwarderMetricsConsumer.cs +++ b/testassets/ReverseProxy.Code/ForwarderMetricsConsumer.cs @@ -6,13 +6,13 @@ namespace Yarp.ReverseProxy.Sample { - public sealed class ForwarderMetricsConsumer : IForwarderMetricsConsumer + public sealed class ForwarderMetricsConsumer : IMetricsConsumer { - public void OnForwarderMetrics(ForwarderMetrics oldMetrics, ForwarderMetrics newMetrics) + public void OnMetrics(ForwarderMetrics previous, ForwarderMetrics current) { - var elapsed = newMetrics.Timestamp - oldMetrics.Timestamp; - var newRequests = newMetrics.RequestsStarted - oldMetrics.RequestsStarted; - Console.Title = $"Proxied {newMetrics.RequestsStarted} requests ({newRequests} in the last {(int)elapsed.TotalMilliseconds} ms)"; + var elapsed = current.Timestamp - previous.Timestamp; + var newRequests = current.RequestsStarted - previous.RequestsStarted; + Console.Title = $"Proxied {current.RequestsStarted} requests ({newRequests} in the last {(int)elapsed.TotalMilliseconds} ms)"; } } } diff --git a/testassets/ReverseProxy.Code/Startup.cs b/testassets/ReverseProxy.Code/Startup.cs index 5482db170..cdaec414d 100644 --- a/testassets/ReverseProxy.Code/Startup.cs +++ b/testassets/ReverseProxy.Code/Startup.cs @@ -92,7 +92,7 @@ public void ConfigureServices(IServiceCollection services) }); services.AddHttpContextAccessor(); - services.AddSingleton(); + services.AddSingleton, ForwarderMetricsConsumer>(); services.AddTelemetryConsumer(); services.AddTelemetryListeners(); }