From 89d9814ea0b59655856a66703ba06ca636296575 Mon Sep 17 00:00:00 2001 From: kkeirstead Date: Mon, 17 Apr 2023 10:51:12 -0700 Subject: [PATCH 1/6] Started using value for UDC --- .../Counters/TraceEventExtensions.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs index eedc106d18..40aea6ff1e 100644 --- a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs @@ -90,6 +90,10 @@ public static bool TryGetCounterPayload(this TraceEvent traceEvent, CounterFilte { HandleCounterRate(traceEvent, filter, sessionId, out payload); } + else if (traceEvent.EventName == "UpDownCounterRateValuePublished") + { + HandleUpDownCounterRate(traceEvent, filter, sessionId, out payload); + } else if (traceEvent.EventName == "TimeSeriesLimitReached") { HandleTimeSeriesLimitReached(traceEvent, sessionId, out payload); @@ -170,6 +174,7 @@ private static void HandleCounterRate(TraceEvent traceEvent, CounterFilter filte string unit = (string)traceEvent.PayloadValue(4); string tags = (string)traceEvent.PayloadValue(5); string rateText = (string)traceEvent.PayloadValue(6); + _ = (string)traceEvent.PayloadValue(7); // Not currently using value for Counters. if (!filter.IsIncluded(meterName, instrumentName)) { @@ -188,6 +193,45 @@ private static void HandleCounterRate(TraceEvent traceEvent, CounterFilter filte } } + private static void HandleUpDownCounterRate(TraceEvent traceEvent, CounterFilter filter, string sessionId, out ICounterPayload payload) + { + payload = null; + + string payloadSessionId = (string)traceEvent.PayloadValue(0); + + if (payloadSessionId != sessionId) + { + return; + } + + string meterName = (string)traceEvent.PayloadValue(1); + //string meterVersion = (string)obj.PayloadValue(2); + string instrumentName = (string)traceEvent.PayloadValue(3); + string unit = (string)traceEvent.PayloadValue(4); + string tags = (string)traceEvent.PayloadValue(5); + _ = (string)traceEvent.PayloadValue(6); // Not currently using rate for Counters. + string valueText = (string)traceEvent.PayloadValue(7); + + if (!filter.IsIncluded(meterName, instrumentName)) + { + return; + } + + if (double.TryParse(valueText, NumberStyles.Number | NumberStyles.Float, CultureInfo.InvariantCulture, out double value)) + { + // UpDownCounter reports the value, not the rate - this is different than how Counter behaves. + //payload = new RatePayload(meterName, instrumentName, null, unit, tags, rate, filter.DefaultIntervalSeconds, traceEvent.TimeStamp); + payload = new GaugePayload(meterName, instrumentName, null, unit, tags, value, traceEvent.TimeStamp); + + } + else + { + // for observable instruments we assume the lack of data is meaningful and remove it from the UI + // this happens when the ObservableCounter callback function throws an exception. + payload = new CounterEndedPayload(meterName, instrumentName, traceEvent.TimeStamp); + } + } + private static void HandleHistogram(TraceEvent obj, CounterFilter filter, string sessionId, out ICounterPayload payload) { payload = null; From e0cfa8f816094eb5871d5b41fcd38f60d2491c7f Mon Sep 17 00:00:00 2001 From: kkeirstead Date: Mon, 17 Apr 2023 12:24:52 -0700 Subject: [PATCH 2/6] Adding support for UpDownCounter reporting a value instead of a rate --- .../Counters/CounterPayload.cs | 12 +++++++ .../Counters/TraceEventExtensions.cs | 8 ++--- src/Tools/dotnet-counters/CounterMonitor.cs | 35 +++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/CounterPayload.cs b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/CounterPayload.cs index 18eb5264e3..99e3030081 100644 --- a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/CounterPayload.cs +++ b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/CounterPayload.cs @@ -86,6 +86,17 @@ public GaugePayload(string providerName, string name, string displayName, string } } + internal class UpDownCounterPayload : CounterPayload + { + public UpDownCounterPayload(string providerName, string name, string displayName, string displayUnits, string metadata, double value, DateTime timestamp) : + base(providerName, name, metadata, value, timestamp, "Metric", EventType.UpDownCounter) + { + // In case these properties are not provided, set them to appropriate values. + string counterName = string.IsNullOrEmpty(displayName) ? name : displayName; + DisplayName = !string.IsNullOrEmpty(displayUnits) ? $"{counterName} ({displayUnits})" : counterName; + } + } + internal class CounterEndedPayload : CounterPayload { public CounterEndedPayload(string providerName, string name, DateTime timestamp) @@ -144,6 +155,7 @@ internal enum EventType : int Rate, Gauge, Histogram, + UpDownCounter, Error, CounterEnded } diff --git a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs index 40aea6ff1e..70c1fdfb1e 100644 --- a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs @@ -92,7 +92,7 @@ public static bool TryGetCounterPayload(this TraceEvent traceEvent, CounterFilte } else if (traceEvent.EventName == "UpDownCounterRateValuePublished") { - HandleUpDownCounterRate(traceEvent, filter, sessionId, out payload); + HandleUpDownCounterValue(traceEvent, filter, sessionId, out payload); } else if (traceEvent.EventName == "TimeSeriesLimitReached") { @@ -193,7 +193,7 @@ private static void HandleCounterRate(TraceEvent traceEvent, CounterFilter filte } } - private static void HandleUpDownCounterRate(TraceEvent traceEvent, CounterFilter filter, string sessionId, out ICounterPayload payload) + private static void HandleUpDownCounterValue(TraceEvent traceEvent, CounterFilter filter, string sessionId, out ICounterPayload payload) { payload = null; @@ -209,7 +209,7 @@ private static void HandleUpDownCounterRate(TraceEvent traceEvent, CounterFilter string instrumentName = (string)traceEvent.PayloadValue(3); string unit = (string)traceEvent.PayloadValue(4); string tags = (string)traceEvent.PayloadValue(5); - _ = (string)traceEvent.PayloadValue(6); // Not currently using rate for Counters. + _ = (string)traceEvent.PayloadValue(6); // Not currently using rate for UpDownCounters. string valueText = (string)traceEvent.PayloadValue(7); if (!filter.IsIncluded(meterName, instrumentName)) @@ -221,7 +221,7 @@ private static void HandleUpDownCounterRate(TraceEvent traceEvent, CounterFilter { // UpDownCounter reports the value, not the rate - this is different than how Counter behaves. //payload = new RatePayload(meterName, instrumentName, null, unit, tags, rate, filter.DefaultIntervalSeconds, traceEvent.TimeStamp); - payload = new GaugePayload(meterName, instrumentName, null, unit, tags, value, traceEvent.TimeStamp); + payload = new UpDownCounterPayload(meterName, instrumentName, null, unit, tags, value, traceEvent.TimeStamp); } else diff --git a/src/Tools/dotnet-counters/CounterMonitor.cs b/src/Tools/dotnet-counters/CounterMonitor.cs index 928664d33e..c65ef75d55 100644 --- a/src/Tools/dotnet-counters/CounterMonitor.cs +++ b/src/Tools/dotnet-counters/CounterMonitor.cs @@ -18,6 +18,7 @@ using Microsoft.Diagnostics.Tools.Counters.Exporters; using Microsoft.Diagnostics.Tracing; using Microsoft.Internal.Common.Utils; +using static System.Net.WebRequestMethods; namespace Microsoft.Diagnostics.Tools.Counters { @@ -88,6 +89,10 @@ private void DynamicAllMonitor(TraceEvent obj) { HandleCounterRate(obj); } + else if (obj.EventName == "UpDownCounterRateValuePublished") + { + HandleUpDownCounterValue(obj); + } else if (obj.EventName == "TimeSeriesLimitReached") { HandleTimeSeriesLimitReached(obj); @@ -198,6 +203,36 @@ private void HandleGauge(TraceEvent obj) } } + private void HandleUpDownCounterValue(TraceEvent obj) + { + string sessionId = (string)obj.PayloadValue(0); + string meterName = (string)obj.PayloadValue(1); + //string meterVersion = (string)obj.PayloadValue(2); + string instrumentName = (string)obj.PayloadValue(3); + string unit = (string)obj.PayloadValue(4); + string tags = (string)obj.PayloadValue(5); + _ = (string)obj.PayloadValue(6); // Not currently using rate for UpDownCounters. + string valueText = (string)obj.PayloadValue(7); + if (sessionId != _metricsEventSourceSessionId) + { + return; + } + MeterInstrumentEventObserved(meterName, obj.TimeStamp); + + // the value might be an empty string indicating no measurement was provided this collection interval + if (double.TryParse(valueText, NumberStyles.Number | NumberStyles.Float, CultureInfo.InvariantCulture, out double value)) + { + CounterPayload payload = new GaugePayload(meterName, instrumentName, null, unit, tags, value, obj.TimeStamp); + _renderer.CounterPayloadReceived(payload, _pauseCmdSet); + } + else + { + // for observable instruments we assume the lack of data is meaningful and remove it from the UI + CounterPayload payload = new RatePayload(meterName, instrumentName, null, unit, tags, 0, _interval, obj.TimeStamp); + _renderer.CounterStopped(payload); + } + } + private void HandleHistogram(TraceEvent obj) { string sessionId = (string)obj.PayloadValue(0); From 281f7c5aeaa0ebf2e01a50a3ccc1d5588dd656d6 Mon Sep 17 00:00:00 2001 From: kkeirstead Date: Thu, 20 Apr 2023 09:35:35 -0700 Subject: [PATCH 3/6] Some cleanup --- .../Counters/TraceEventExtensions.cs | 3 +-- src/Tools/dotnet-counters/CounterMonitor.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs index 70c1fdfb1e..1e8a512488 100644 --- a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs @@ -220,14 +220,13 @@ private static void HandleUpDownCounterValue(TraceEvent traceEvent, CounterFilte if (double.TryParse(valueText, NumberStyles.Number | NumberStyles.Float, CultureInfo.InvariantCulture, out double value)) { // UpDownCounter reports the value, not the rate - this is different than how Counter behaves. - //payload = new RatePayload(meterName, instrumentName, null, unit, tags, rate, filter.DefaultIntervalSeconds, traceEvent.TimeStamp); payload = new UpDownCounterPayload(meterName, instrumentName, null, unit, tags, value, traceEvent.TimeStamp); } else { // for observable instruments we assume the lack of data is meaningful and remove it from the UI - // this happens when the ObservableCounter callback function throws an exception. + // this happens when the ObservableUpDownCounter callback function throws an exception. payload = new CounterEndedPayload(meterName, instrumentName, traceEvent.TimeStamp); } } diff --git a/src/Tools/dotnet-counters/CounterMonitor.cs b/src/Tools/dotnet-counters/CounterMonitor.cs index c65ef75d55..3a0b19e935 100644 --- a/src/Tools/dotnet-counters/CounterMonitor.cs +++ b/src/Tools/dotnet-counters/CounterMonitor.cs @@ -18,7 +18,6 @@ using Microsoft.Diagnostics.Tools.Counters.Exporters; using Microsoft.Diagnostics.Tracing; using Microsoft.Internal.Common.Utils; -using static System.Net.WebRequestMethods; namespace Microsoft.Diagnostics.Tools.Counters { @@ -222,6 +221,7 @@ private void HandleUpDownCounterValue(TraceEvent obj) // the value might be an empty string indicating no measurement was provided this collection interval if (double.TryParse(valueText, NumberStyles.Number | NumberStyles.Float, CultureInfo.InvariantCulture, out double value)) { + // UpDownCounter reports the value, not the rate - this is different than how Counter behaves, and is thus treated as a gauge. CounterPayload payload = new GaugePayload(meterName, instrumentName, null, unit, tags, value, obj.TimeStamp); _renderer.CounterPayloadReceived(payload, _pauseCmdSet); } From 2a04557beaba2958e331a878441deb3114aea1fd Mon Sep 17 00:00:00 2001 From: kkeirstead Date: Mon, 24 Apr 2023 08:56:58 -0700 Subject: [PATCH 4/6] Check for payload version, don't attempt to parse if version 0 --- .../Counters/TraceEventExtensions.cs | 3 +-- src/Tools/dotnet-counters/CounterMonitor.cs | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs index 1e8a512488..3f6b51e5b8 100644 --- a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs @@ -174,7 +174,6 @@ private static void HandleCounterRate(TraceEvent traceEvent, CounterFilter filte string unit = (string)traceEvent.PayloadValue(4); string tags = (string)traceEvent.PayloadValue(5); string rateText = (string)traceEvent.PayloadValue(6); - _ = (string)traceEvent.PayloadValue(7); // Not currently using value for Counters. if (!filter.IsIncluded(meterName, instrumentName)) { @@ -199,7 +198,7 @@ private static void HandleUpDownCounterValue(TraceEvent traceEvent, CounterFilte string payloadSessionId = (string)traceEvent.PayloadValue(0); - if (payloadSessionId != sessionId) + if (payloadSessionId != sessionId || traceEvent.Version < 1) // Version 1 added the value field. { return; } diff --git a/src/Tools/dotnet-counters/CounterMonitor.cs b/src/Tools/dotnet-counters/CounterMonitor.cs index 3a0b19e935..54aec06dcd 100644 --- a/src/Tools/dotnet-counters/CounterMonitor.cs +++ b/src/Tools/dotnet-counters/CounterMonitor.cs @@ -204,6 +204,11 @@ private void HandleGauge(TraceEvent obj) private void HandleUpDownCounterValue(TraceEvent obj) { + if (obj.Version < 1) // Version 1 added the value field. + { + return; + } + string sessionId = (string)obj.PayloadValue(0); string meterName = (string)obj.PayloadValue(1); //string meterVersion = (string)obj.PayloadValue(2); From 45029f1b5c3c19127dcd0feeef895dc6aa4b0a43 Mon Sep 17 00:00:00 2001 From: kkeirstead Date: Mon, 24 Apr 2023 11:50:11 -0700 Subject: [PATCH 5/6] Don't get rate for updowncounter payload (just comment it out to make it clear that the payload does contain this information). --- .../Counters/TraceEventExtensions.cs | 2 +- src/Tools/dotnet-counters/CounterMonitor.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs index 3f6b51e5b8..cc97331ac3 100644 --- a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs @@ -208,7 +208,7 @@ private static void HandleUpDownCounterValue(TraceEvent traceEvent, CounterFilte string instrumentName = (string)traceEvent.PayloadValue(3); string unit = (string)traceEvent.PayloadValue(4); string tags = (string)traceEvent.PayloadValue(5); - _ = (string)traceEvent.PayloadValue(6); // Not currently using rate for UpDownCounters. + //string rateText = (string)traceEvent.PayloadValue(6); // Not currently using rate for UpDownCounters. string valueText = (string)traceEvent.PayloadValue(7); if (!filter.IsIncluded(meterName, instrumentName)) diff --git a/src/Tools/dotnet-counters/CounterMonitor.cs b/src/Tools/dotnet-counters/CounterMonitor.cs index 54aec06dcd..a017074386 100644 --- a/src/Tools/dotnet-counters/CounterMonitor.cs +++ b/src/Tools/dotnet-counters/CounterMonitor.cs @@ -215,7 +215,7 @@ private void HandleUpDownCounterValue(TraceEvent obj) string instrumentName = (string)obj.PayloadValue(3); string unit = (string)obj.PayloadValue(4); string tags = (string)obj.PayloadValue(5); - _ = (string)obj.PayloadValue(6); // Not currently using rate for UpDownCounters. + //string rateText = (string)obj.PayloadValue(6); // Not currently using rate for UpDownCounters. string valueText = (string)obj.PayloadValue(7); if (sessionId != _metricsEventSourceSessionId) { From 94a5a3d57ff8e4c9209792e8a61cf21c1d8d456e Mon Sep 17 00:00:00 2001 From: kkeirstead <85592574+kkeirstead@users.noreply.github.com> Date: Mon, 1 May 2023 10:07:52 -0700 Subject: [PATCH 6/6] Update comments --- .../Counters/TraceEventExtensions.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs index cc97331ac3..347a4e11f2 100644 --- a/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs +++ b/src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs @@ -187,7 +187,8 @@ private static void HandleCounterRate(TraceEvent traceEvent, CounterFilter filte else { // for observable instruments we assume the lack of data is meaningful and remove it from the UI - // this happens when the ObservableCounter callback function throws an exception. + // this happens when the ObservableCounter callback function throws an exception + // or when the ObservableCounter doesn't include a measurement for a particular set of tag values. payload = new CounterEndedPayload(meterName, instrumentName, traceEvent.TimeStamp); } } @@ -225,7 +226,8 @@ private static void HandleUpDownCounterValue(TraceEvent traceEvent, CounterFilte else { // for observable instruments we assume the lack of data is meaningful and remove it from the UI - // this happens when the ObservableUpDownCounter callback function throws an exception. + // this happens when the ObservableUpDownCounter callback function throws an exception + // or when the ObservableUpDownCounter doesn't include a measurement for a particular set of tag values. payload = new CounterEndedPayload(meterName, instrumentName, traceEvent.TimeStamp); } }