From dfe1076090adad6990747e6abed8bf6699371877 Mon Sep 17 00:00:00 2001
From: kkeirstead <85592574+kkeirstead@users.noreply.github.com>
Date: Sat, 28 Jan 2023 16:56:15 -0800
Subject: [PATCH] Publish `UpDownCounter` and `ObservableUpDownCounter` Events
for System.Diagnostics.Metrics (#81041)
Add support for publishing UpDownCounter (and Observable...) - also added in the missing testing for this.
---
.../Diagnostics/Metrics/AggregationManager.cs | 24 +++-
.../Diagnostics/Metrics/MetricsEventSource.cs | 20 ++-
.../System/Diagnostics/Metrics/RateAggregator.cs | 21 +++-
.../tests/MetricEventSourceTests.cs | 139 ++++++++++++++++++---
.../tests/MetricsTests.cs | 3 +
5 files changed, 186 insertions(+), 21 deletions(-)
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/AggregationManager.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/AggregationManager.cs
index 8af2391..770af1d 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/AggregationManager.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/AggregationManager.cs
@@ -275,7 +275,7 @@ namespace System.Diagnostics.Metrics
{
lock (this)
{
- return CheckTimeSeriesAllowed() ? new RateSumAggregator() : null;
+ return CheckTimeSeriesAllowed() ? new RateSumAggregator(isMonotonic: true) : null;
}
};
}
@@ -285,7 +285,7 @@ namespace System.Diagnostics.Metrics
{
lock (this)
{
- return CheckTimeSeriesAllowed() ? new RateAggregator() : null;
+ return CheckTimeSeriesAllowed() ? new RateAggregator(isMonotonic: true) : null;
}
};
}
@@ -312,6 +312,26 @@ namespace System.Diagnostics.Metrics
}
};
}
+ else if (genericDefType == typeof(UpDownCounter<>))
+ {
+ return () =>
+ {
+ lock (this)
+ {
+ return CheckTimeSeriesAllowed() ? new RateSumAggregator(isMonotonic: false) : null;
+ }
+ };
+ }
+ else if (genericDefType == typeof(ObservableUpDownCounter<>))
+ {
+ return () =>
+ {
+ lock (this)
+ {
+ return CheckTimeSeriesAllowed() ? new RateAggregator(isMonotonic: false) : null;
+ }
+ };
+ }
else
{
return null;
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs
index 8b2fd37..79a5b78 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs
@@ -191,6 +191,14 @@ namespace System.Diagnostics.Metrics
WriteEvent(15, runningSessionId);
}
+ [Event(16, Keywords = Keywords.TimeSeriesValues)]
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This calls WriteEvent with all primitive arguments which is safe. Primitives are always serialized properly.")]
+ public void UpDownCounterRateValuePublished(string sessionId, string meterName, string? meterVersion, string instrumentName, string? unit, string tags, string rate)
+ {
+ WriteEvent(16, sessionId, meterName, meterVersion ?? "", instrumentName, unit ?? "", tags, rate);
+ }
+
///
/// Called when the EventSource gets a command from a EventListener or ETW.
///
@@ -407,8 +415,16 @@ namespace System.Diagnostics.Metrics
{
if (stats.AggregationStatistics is RateStatistics rateStats)
{
- Log.CounterRateValuePublished(sessionId, instrument.Meter.Name, instrument.Meter.Version, instrument.Name, instrument.Unit, FormatTags(stats.Labels),
- rateStats.Delta.HasValue ? rateStats.Delta.Value.ToString(CultureInfo.InvariantCulture) : "");
+ if (rateStats.IsMonotonic)
+ {
+ Log.CounterRateValuePublished(sessionId, instrument.Meter.Name, instrument.Meter.Version, instrument.Name, instrument.Unit, FormatTags(stats.Labels),
+ rateStats.Delta.HasValue ? rateStats.Delta.Value.ToString(CultureInfo.InvariantCulture) : "");
+ }
+ else
+ {
+ Log.UpDownCounterRateValuePublished(sessionId, instrument.Meter.Name, instrument.Meter.Version, instrument.Name, instrument.Unit, FormatTags(stats.Labels),
+ rateStats.Delta.HasValue ? rateStats.Delta.Value.ToString(CultureInfo.InvariantCulture) : "");
+ }
}
else if (stats.AggregationStatistics is LastValueStatistics lastValueStats)
{
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/RateAggregator.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/RateAggregator.cs
index dc27288..d1109f5 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/RateAggregator.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/RateAggregator.cs
@@ -6,6 +6,12 @@ namespace System.Diagnostics.Metrics
internal sealed class RateSumAggregator : Aggregator
{
private double _sum;
+ private bool _isMonotonic;
+
+ public RateSumAggregator(bool isMonotonic)
+ {
+ _isMonotonic = isMonotonic;
+ }
public override void Update(double value)
{
@@ -19,7 +25,7 @@ namespace System.Diagnostics.Metrics
{
lock (this)
{
- RateStatistics? stats = new RateStatistics(_sum);
+ RateStatistics? stats = new RateStatistics(_sum, _isMonotonic);
_sum = 0;
return stats;
}
@@ -30,6 +36,12 @@ namespace System.Diagnostics.Metrics
{
private double? _prevValue;
private double _value;
+ private bool _isMonotonic;
+
+ public RateAggregator(bool isMonotonic)
+ {
+ _isMonotonic = isMonotonic;
+ }
public override void Update(double value)
{
@@ -48,7 +60,7 @@ namespace System.Diagnostics.Metrics
{
delta = _value - _prevValue.Value;
}
- RateStatistics stats = new RateStatistics(delta);
+ RateStatistics stats = new RateStatistics(delta, _isMonotonic);
_prevValue = _value;
return stats;
}
@@ -57,11 +69,14 @@ namespace System.Diagnostics.Metrics
internal sealed class RateStatistics : IAggregationStatistics
{
- public RateStatistics(double? delta)
+ public RateStatistics(double? delta, bool isMonotonic)
{
Delta = delta;
+ IsMonotonic = isMonotonic;
}
public double? Delta { get; }
+
+ public bool IsMonotonic { get; }
}
}
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs
index b468bbd..e85ebbe 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricEventSourceTests.cs
@@ -35,6 +35,9 @@ namespace System.Diagnostics.Metrics.Tests
int gaugeState = 0;
ObservableGauge og = meter.CreateObservableGauge("observableGauge1", () => { gaugeState += 9; return gaugeState; });
Histogram h = meter.CreateHistogram("histogram1");
+ UpDownCounter udc = meter.CreateUpDownCounter("upDownCounter1");
+ int upDownCounterState = 0;
+ ObservableUpDownCounter oudc = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () => { upDownCounterState -= 11; return upDownCounterState; });
EventWrittenEventArgs[] events;
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, "TestMeter1"))
@@ -42,19 +45,23 @@ namespace System.Diagnostics.Metrics.Tests
listener.WaitForCollectionStop(s_waitForEventTimeout, 1);
c.Add(5);
h.Record(19);
+ udc.Add(-33);
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
c.Add(12);
h.Record(26);
+ udc.Add(-40);
listener.WaitForCollectionStop(s_waitForEventTimeout, 3);
events = listener.Events.ToArray();
}
- AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h);
+ AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
AssertInitialEnumerationCompleteEventPresent(events);
AssertCounterEventsPresent(events, meter.Name, c.Name, "", "", "5", "12");
AssertCounterEventsPresent(events, meter.Name, oc.Name, "", "", "", "7");
AssertGaugeEventsPresent(events, meter.Name, og.Name, "", "", "9", "18");
AssertHistogramEventsPresent(events, meter.Name, h.Name, "", "", "0.5=19;0.95=19;0.99=19", "0.5=26;0.95=26;0.99=26");
+ AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "", "", "-33", "-40");
+ AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "", "", "", "-11");
AssertCollectStartStopEventsPresent(events, IntervalSecs, 3);
}
@@ -69,6 +76,9 @@ namespace System.Diagnostics.Metrics.Tests
int gaugeState = 0;
ObservableGauge og = meter.CreateObservableGauge("observableGauge1", () => { gaugeState += 9; return gaugeState; }, "12394923 asd [],;/", "junk!");
Histogram h = meter.CreateHistogram("histogram1", "a unit", "the description");
+ UpDownCounter udc = meter.CreateUpDownCounter("upDownCounter1", "udc unit", "udc description");
+ int upDownCounterState = 0;
+ ObservableUpDownCounter oudc = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () => { upDownCounterState += 11; return upDownCounterState; }, "oudc unit", "oudc description");
EventWrittenEventArgs[] events;
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, "TestMeter2"))
@@ -76,19 +86,23 @@ namespace System.Diagnostics.Metrics.Tests
listener.WaitForCollectionStop(s_waitForEventTimeout, 1);
c.Add(5);
h.Record(19);
+ udc.Add(33);
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
c.Add(12);
h.Record(26);
+ udc.Add(40);
listener.WaitForCollectionStop(s_waitForEventTimeout, 3);
events = listener.Events.ToArray();
}
- AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h);
+ AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
AssertInitialEnumerationCompleteEventPresent(events);
AssertCounterEventsPresent(events, meter.Name, c.Name, "", c.Unit, "5", "12");
AssertCounterEventsPresent(events, meter.Name, oc.Name, "", oc.Unit, "", "7", "7");
AssertGaugeEventsPresent(events, meter.Name, og.Name, "", og.Unit, "9", "18", "27");
AssertHistogramEventsPresent(events, meter.Name, h.Name, "", h.Unit, "0.5=19;0.95=19;0.99=19", "0.5=26;0.95=26;0.99=26");
+ AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "", udc.Unit, "33", "40");
+ AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "", oudc.Unit, "", "11");
AssertCollectStartStopEventsPresent(events, IntervalSecs, 3);
}
@@ -105,6 +119,8 @@ namespace System.Diagnostics.Metrics.Tests
ObservableCounter oc;
ObservableGauge og;
Histogram h;
+ UpDownCounter udc;
+ ObservableUpDownCounter oudc;
EventWrittenEventArgs[] events;
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, "TestMeter3"))
@@ -119,22 +135,29 @@ namespace System.Diagnostics.Metrics.Tests
int gaugeState = 0;
og = meter.CreateObservableGauge("observableGauge1", () => { gaugeState += 9; return gaugeState; });
h = meter.CreateHistogram("histogram1");
+ udc = meter.CreateUpDownCounter("upDownCounter1");
+ int upDownCounterState = 0;
+ oudc = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () => { upDownCounterState -= 11; return upDownCounterState; });
c.Add(5);
h.Record(19);
+ udc.Add(33);
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
c.Add(12);
h.Record(26);
+ udc.Add(40);
listener.WaitForCollectionStop(s_waitForEventTimeout, 3);
events = listener.Events.ToArray();
}
- AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h);
+ AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
AssertInitialEnumerationCompleteEventPresent(events);
AssertCounterEventsPresent(events, meter.Name, c.Name, "", "", "5", "12");
AssertCounterEventsPresent(events, meter.Name, oc.Name, "", "", "", "7");
AssertGaugeEventsPresent(events, meter.Name, og.Name, "", "", "9", "18");
AssertHistogramEventsPresent(events, meter.Name, h.Name, "", "", "0.5=19;0.95=19;0.99=19", "0.5=26;0.95=26;0.99=26");
+ AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "", "", "33", "40");
+ AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "", "", "", "-11");
AssertCollectStartStopEventsPresent(events, IntervalSecs, 3);
}
finally
@@ -153,6 +176,8 @@ namespace System.Diagnostics.Metrics.Tests
ObservableCounter oc;
ObservableGauge og;
Histogram h;
+ UpDownCounter udc;
+ ObservableUpDownCounter oudc;
EventWrittenEventArgs[] events;
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, "TestMeter4"))
@@ -166,22 +191,29 @@ namespace System.Diagnostics.Metrics.Tests
int gaugeState = 0;
og = meter.CreateObservableGauge("observableGauge1", () => { gaugeState += 9; return gaugeState; });
h = meter.CreateHistogram("histogram1");
+ udc = meter.CreateUpDownCounter("upDownCounter1");
+ int upDownCounterState = 0;
+ oudc = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () => { upDownCounterState += 11; return upDownCounterState; });
c.Add(5);
h.Record(19);
+ udc.Add(-33);
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
c.Add(12);
h.Record(26);
+ udc.Add(-40);
listener.WaitForCollectionStop(s_waitForEventTimeout, 3);
events = listener.Events.ToArray();
}
- AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h);
+ AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
AssertInitialEnumerationCompleteEventPresent(events);
AssertCounterEventsPresent(events, meter.Name, c.Name, "", "", "5", "12");
AssertCounterEventsPresent(events, meter.Name, oc.Name, "", "", "", "7");
AssertGaugeEventsPresent(events, meter.Name, og.Name, "", "", "9", "18");
AssertHistogramEventsPresent(events, meter.Name, h.Name, "", "", "0.5=19;0.95=19;0.99=19", "0.5=26;0.95=26;0.99=26");
+ AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "", "", "-33", "-40");
+ AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "", "", "", "11");
AssertCollectStartStopEventsPresent(events, IntervalSecs, 3);
}
@@ -212,6 +244,17 @@ namespace System.Diagnostics.Metrics.Tests
};
});
Histogram h = meter.CreateHistogram("histogram1");
+ UpDownCounter udc = meter.CreateUpDownCounter("upDownCounter1");
+ int upDownCounterState = 0;
+ ObservableUpDownCounter oudc = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () =>
+ {
+ upDownCounterState -= 11;
+ return new Measurement[]
+ {
+ new Measurement(upDownCounterState, new KeyValuePair("Color", "red"), new KeyValuePair("Size", 19) ),
+ new Measurement(2*upDownCounterState, new KeyValuePair("Color", "blue"), new KeyValuePair("Size", 4 ) )
+ };
+ });
EventWrittenEventArgs[] events;
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, "TestMeter5"))
@@ -222,17 +265,21 @@ namespace System.Diagnostics.Metrics.Tests
c.Add(6, new KeyValuePair("Color", "blue"));
h.Record(19, new KeyValuePair("Size", 123));
h.Record(20, new KeyValuePair("Size", 124));
+ udc.Add(-33, new KeyValuePair("Color", "red"));
+ udc.Add(-34, new KeyValuePair("Color", "blue"));
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
c.Add(12, new KeyValuePair("Color", "red"));
c.Add(13, new KeyValuePair("Color", "blue"));
h.Record(26, new KeyValuePair("Size", 123));
h.Record(27, new KeyValuePair("Size", 124));
+ udc.Add(40, new KeyValuePair("Color", "red"));
+ udc.Add(41, new KeyValuePair("Color", "blue"));
listener.WaitForCollectionStop(s_waitForEventTimeout, 3);
events = listener.Events.ToArray();
}
- AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h);
+ AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
AssertInitialEnumerationCompleteEventPresent(events);
AssertCounterEventsPresent(events, meter.Name, c.Name, "Color=red", "", "5", "12");
AssertCounterEventsPresent(events, meter.Name, c.Name, "Color=blue", "", "6", "13");
@@ -242,6 +289,10 @@ namespace System.Diagnostics.Metrics.Tests
AssertGaugeEventsPresent(events, meter.Name, og.Name, "Color=blue,Size=4", "", "18", "36");
AssertHistogramEventsPresent(events, meter.Name, h.Name, "Size=123", "", "0.5=19;0.95=19;0.99=19", "0.5=26;0.95=26;0.99=26");
AssertHistogramEventsPresent(events, meter.Name, h.Name, "Size=124", "", "0.5=20;0.95=20;0.99=20", "0.5=27;0.95=27;0.99=27");
+ AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "Color=red", "", "-33", "40");
+ AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "Color=blue", "", "-34", "41");
+ AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "Color=red,Size=19", "", "", "-11");
+ AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "Color=blue,Size=4", "", "", "-22");
AssertCollectStartStopEventsPresent(events, IntervalSecs, 3);
}
@@ -348,6 +399,23 @@ namespace System.Diagnostics.Metrics.Tests
Histogram h = meter.CreateHistogram("histogram1");
+ UpDownCounter udc = meter.CreateUpDownCounter("upDownCounter1");
+ int upDownCounterState = 0;
+ int upDownCounterCollectInterval = 0;
+ ObservableUpDownCounter oudc = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () =>
+ {
+ upDownCounterState += 11;
+ upDownCounterCollectInterval++;
+ if ((upDownCounterCollectInterval % 2) == 0)
+ {
+ return new Measurement[] { new Measurement(upDownCounterState) };
+ }
+ else
+ {
+ return new Measurement[0];
+ }
+ });
+
EventWrittenEventArgs[] events;
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, "TestMeter6"))
{
@@ -355,23 +423,27 @@ namespace System.Diagnostics.Metrics.Tests
listener.WaitForCollectionStop(s_waitForEventTimeout, 1);
c.Add(5);
h.Record(19);
+ udc.Add(33);
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
// no measurements in interval 3
listener.WaitForCollectionStop(s_waitForEventTimeout, 3);
c.Add(12);
h.Record(26);
+ udc.Add(40);
listener.WaitForCollectionStop(s_waitForEventTimeout, 4);
// no measurements in interval 5
listener.WaitForCollectionStop(s_waitForEventTimeout, 5);
events = listener.Events.ToArray();
}
- AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h);
+ AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
AssertInitialEnumerationCompleteEventPresent(events);
AssertCounterEventsPresent(events, meter.Name, c.Name, "", "", "5", "0", "12");
AssertCounterEventsPresent(events, meter.Name, oc.Name, "", "", "", "0", "14", "0");
AssertGaugeEventsPresent(events, meter.Name, og.Name, "", "", "18", "", "36", "");
AssertHistogramEventsPresent(events, meter.Name, h.Name, "", "", "0.5=19;0.95=19;0.99=19", "", "0.5=26;0.95=26;0.99=26", "");
+ AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "", "", "33", "0", "40");
+ AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "", "", "", "0", "22", "0");
AssertCollectStartStopEventsPresent(events, IntervalSecs, 5);
}
@@ -386,6 +458,9 @@ namespace System.Diagnostics.Metrics.Tests
int gaugeState = 0;
ObservableGauge og = meter.CreateObservableGauge("observableGauge1", () => { gaugeState += 9; return gaugeState; }, "12394923 asd [],;/", "junk!");
Histogram h = meter.CreateHistogram("histogram1", "a unit", "the description");
+ UpDownCounter udc = meter.CreateUpDownCounter("upDownCounter1", "udc unit", "udc description");
+ int upDownCounterState = 0;
+ ObservableUpDownCounter oudc = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () => { upDownCounterState += 11; return upDownCounterState; }, "oudc unit", "oudc description");
EventWrittenEventArgs[] events;
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, "TestMeter7"))
@@ -393,9 +468,11 @@ namespace System.Diagnostics.Metrics.Tests
listener.WaitForCollectionStop(s_waitForEventTimeout, 1);
c.Add(5);
h.Record(19);
+ udc.Add(33);
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
c.Add(12);
h.Record(26);
+ udc.Add(40);
// some alternate listener attempts to listen in the middle
using MetricsEventListener listener2 = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, "ADifferentMeter");
@@ -406,11 +483,13 @@ namespace System.Diagnostics.Metrics.Tests
events = listener.Events.ToArray();
}
- AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h);
+ AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
AssertCounterEventsPresent(events, meter.Name, c.Name, "", c.Unit, "5", "12");
AssertCounterEventsPresent(events, meter.Name, oc.Name, "", oc.Unit, "", "7", "7");
AssertGaugeEventsPresent(events, meter.Name, og.Name, "", og.Unit, "9", "18", "27");
AssertHistogramEventsPresent(events, meter.Name, h.Name, "", h.Unit, "0.5=19;0.95=19;0.99=19", "0.5=26;0.95=26;0.99=26");
+ AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "", udc.Unit, "33", "40");
+ AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "", oudc.Unit, "", "11");
AssertCollectStartStopEventsPresent(events, IntervalSecs, 3);
}
@@ -426,6 +505,9 @@ namespace System.Diagnostics.Metrics.Tests
int gaugeState = 0;
ObservableGauge og = meterA.CreateObservableGauge("observableGauge1", () => { gaugeState += 9; return gaugeState; }, "12394923 asd [],;/", "junk!");
Histogram h = meterB.CreateHistogram("histogram1", "a unit", "the description");
+ UpDownCounter udc = meterA.CreateUpDownCounter("upDownCounter1", "udc unit", "udc description");
+ int upDownCounterState = 0;
+ ObservableUpDownCounter oudc = meterA.CreateObservableUpDownCounter("observableUpDownCounter1", () => { upDownCounterState += 11; return upDownCounterState; }, "oudc unit", "oudc description");
EventWrittenEventArgs[] events;
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, "TestMeter8;TestMeter9"))
@@ -433,9 +515,11 @@ namespace System.Diagnostics.Metrics.Tests
listener.WaitForCollectionStop(s_waitForEventTimeout, 1);
c.Add(5);
h.Record(19);
+ udc.Add(33);
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
c.Add(12);
h.Record(26);
+ udc.Add(40);
listener.WaitForCollectionStop(s_waitForEventTimeout, 3);
meterA.Dispose();
@@ -446,14 +530,16 @@ namespace System.Diagnostics.Metrics.Tests
events = listener.Events.ToArray();
}
- AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h);
+ AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
AssertInitialEnumerationCompleteEventPresent(events);
AssertCounterEventsPresent(events, meterA.Name, c.Name, "", c.Unit, "5", "12");
AssertCounterEventsPresent(events, meterA.Name, oc.Name, "", oc.Unit, "", "7", "7");
AssertGaugeEventsPresent(events, meterA.Name, og.Name, "", og.Unit, "9", "18", "27");
AssertHistogramEventsPresent(events, meterB.Name, h.Name, "", h.Unit, "0.5=19;0.95=19;0.99=19", "0.5=26;0.95=26;0.99=26", "0.5=21;0.95=21;0.99=21");
+ AssertUpDownCounterEventsPresent(events, meterA.Name, udc.Name, "", udc.Unit, "33", "40");
+ AssertUpDownCounterEventsPresent(events, meterA.Name, oudc.Name, "", oudc.Unit, "", "11", "11");
AssertCollectStartStopEventsPresent(events, IntervalSecs, 4);
- AssertEndInstrumentReportingEventsPresent(events, c, oc, og);
+ AssertEndInstrumentReportingEventsPresent(events, c, oc, og, udc, oudc);
}
@@ -469,6 +555,9 @@ namespace System.Diagnostics.Metrics.Tests
int gaugeState = 0;
ObservableGauge og = meterA.CreateObservableGauge("observableGauge1", () => { gaugeState += 9; return gaugeState; }, "12394923 asd [],;/", "junk!");
Histogram h = meterB.CreateHistogram("histogram1", "a unit", "the description");
+ UpDownCounter udc = meterA.CreateUpDownCounter("upDownCounter1", "udc unit", "udc description");
+ int upDownCounterState = 0;
+ ObservableUpDownCounter oudc = meterA.CreateObservableUpDownCounter("observableUpDownCounter1", () => { upDownCounterState += 11; return upDownCounterState; }, "oudc unit", "oudc description");
EventWrittenEventArgs[] events;
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.InstrumentPublishing, null, ""))
@@ -477,7 +566,7 @@ namespace System.Diagnostics.Metrics.Tests
events = listener.Events.ToArray();
}
- AssertInstrumentPublishingEventsPresent(events, c, oc, og, h);
+ AssertInstrumentPublishingEventsPresent(events, c, oc, og, h, udc, oudc);
AssertInitialEnumerationCompleteEventPresent(events);
}
@@ -553,7 +642,6 @@ namespace System.Diagnostics.Metrics.Tests
{
using Meter meter = new Meter("TestMeter13");
Counter c = meter.CreateCounter("counter1");
-
EventWrittenEventArgs[] events;
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, 2, 50, "TestMeter13"))
@@ -659,6 +747,9 @@ namespace System.Diagnostics.Metrics.Tests
int gaugeState = 0;
ObservableGauge og = meter.CreateObservableGauge("observableGauge1", () => { gaugeState += 9; return gaugeState; });
Histogram h = meter.CreateHistogram("histogram1");
+ UpDownCounter udc = meter.CreateUpDownCounter("upDownCounter1");
+ int upDownCounterState = 0;
+ ObservableUpDownCounter oudc = meter.CreateObservableUpDownCounter("observableUpDownCounter1", () => { upDownCounterState += 11; return upDownCounterState; });
EventWrittenEventArgs[] events;
using (MetricsEventListener listener = new MetricsEventListener(_output, MetricsEventListener.TimeSeriesValues, IntervalSecs, "TestMeter16"))
@@ -666,19 +757,23 @@ namespace System.Diagnostics.Metrics.Tests
listener.WaitForCollectionStop(s_waitForEventTimeout, 1);
c.Add(5);
h.Record(19);
+ udc.Add(33);
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
c.Add(12);
h.Record(26);
+ udc.Add(40);
listener.WaitForCollectionStop(s_waitForEventTimeout, 3);
events = listener.Events.ToArray();
}
- AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h);
+ AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
AssertInitialEnumerationCompleteEventPresent(events);
AssertCounterEventsPresent(events, meter.Name, c.Name, "", "", "5", "12");
AssertCounterEventsPresent(events, meter.Name, oc.Name, "", "", "", "7");
AssertGaugeEventsPresent(events, meter.Name, og.Name, "", "", "9", "18");
AssertHistogramEventsPresent(events, meter.Name, h.Name, "", "", "0.5=19;0.95=19;0.99=19", "0.5=26;0.95=26;0.99=26");
+ AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "", "", "33", "40");
+ AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "", "", "", "11");
AssertCollectStartStopEventsPresent(events, IntervalSecs, 3);
// Now create a new listener and do everything a 2nd time. Because the listener above has been disposed the source should be
@@ -689,19 +784,23 @@ namespace System.Diagnostics.Metrics.Tests
listener.WaitForCollectionStop(s_waitForEventTimeout, 1);
c.Add(5);
h.Record(19);
+ udc.Add(33);
listener.WaitForCollectionStop(s_waitForEventTimeout, 2);
c.Add(12);
h.Record(26);
+ udc.Add(40);
listener.WaitForCollectionStop(s_waitForEventTimeout, 3);
events = listener.Events.ToArray();
}
- AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h);
+ AssertBeginInstrumentReportingEventsPresent(events, c, oc, og, h, udc, oudc);
AssertInitialEnumerationCompleteEventPresent(events);
AssertCounterEventsPresent(events, meter.Name, c.Name, "", "", "5", "12");
AssertCounterEventsPresent(events, meter.Name, oc.Name, "", "", "", "7");
AssertGaugeEventsPresent(events, meter.Name, og.Name, "", "", "36", "45");
AssertHistogramEventsPresent(events, meter.Name, h.Name, "", "", "0.5=19;0.95=19;0.99=19", "0.5=26;0.95=26;0.99=26");
+ AssertUpDownCounterEventsPresent(events, meter.Name, udc.Name, "", "", "33", "40");
+ AssertUpDownCounterEventsPresent(events, meter.Name, oudc.Name, "", "", "", "11");
AssertCollectStartStopEventsPresent(events, IntervalSecs, 3);
}
@@ -847,7 +946,19 @@ namespace System.Diagnostics.Metrics.Tests
private void AssertCounterEventsPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
string expectedUnit, params string[] expectedRates)
{
- var counterEvents = events.Where(e => e.EventName == "CounterRateValuePublished").Select(e =>
+ AssertGenericCounterEventsPresent("CounterRateValuePublished", events, meterName, instrumentName, tags, expectedUnit, expectedRates);
+ }
+
+ private void AssertUpDownCounterEventsPresent(EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
+ string expectedUnit, params string[] expectedRates)
+ {
+ AssertGenericCounterEventsPresent("UpDownCounterRateValuePublished", events, meterName, instrumentName, tags, expectedUnit, expectedRates);
+ }
+
+ private void AssertGenericCounterEventsPresent(string eventName, EventWrittenEventArgs[] events, string meterName, string instrumentName, string tags,
+ string expectedUnit, params string[] expectedRates)
+ {
+ var counterEvents = events.Where(e => e.EventName == eventName).Select(e =>
new
{
MeterName = e.Payload[1].ToString(),
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs
index 8e5e14b..6f9438e 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/MetricsTests.cs
@@ -849,6 +849,9 @@ namespace System.Diagnostics.Metrics.Tests
counter.Add(1);
Assert.Equal(6, count);
+ upDownCounter.Add(-1);
+ Assert.Equal(6, count);
+
histogram.Record(1);
Assert.Equal(6, count);
--
2.7.4