From 8be4a981203a7be9149c54e5b2c1f45bf8487c73 Mon Sep 17 00:00:00 2001 From: kkeirstead <85592574+kkeirstead@users.noreply.github.com> Date: Wed, 11 Dec 2024 13:46:32 -0800 Subject: [PATCH] Fix `Histogram/UpDownCounter` Custom Tags Bug (#7697) * Added aggregate payload and updowncounter * Added additional tests for histogram and up down counter tags --- .../Metrics/MetricsStore.cs | 2 +- .../MetricsFormattingTests.cs | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Diagnostics.Monitoring.WebApi/Metrics/MetricsStore.cs b/src/Microsoft.Diagnostics.Monitoring.WebApi/Metrics/MetricsStore.cs index 5011bd3caf1..57f37690e4d 100644 --- a/src/Microsoft.Diagnostics.Monitoring.WebApi/Metrics/MetricsStore.cs +++ b/src/Microsoft.Diagnostics.Monitoring.WebApi/Metrics/MetricsStore.cs @@ -186,7 +186,7 @@ private static string GetMetricLabels(ICounterPayload metric, double? quantile) private static bool IsMeter(ICounterPayload payload) => payload switch { - GaugePayload or PercentilePayload or CounterEndedPayload or RatePayload => true, + GaugePayload or PercentilePayload or CounterEndedPayload or RatePayload or AggregatePercentilePayload or UpDownCounterPayload => true, _ => false }; diff --git a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/MetricsFormattingTests.cs b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/MetricsFormattingTests.cs index 5936bc1aa4e..aedc5ce618f 100644 --- a/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/MetricsFormattingTests.cs +++ b/src/Tests/Microsoft.Diagnostics.Monitoring.Tool.UnitTests/MetricsFormattingTests.cs @@ -67,6 +67,37 @@ public async Task HistogramFormat_Test() Assert.Equal(FormattableString.Invariant($"{metricName}{quantile_99} {Value3}"), lines[4]); } + [Fact] + public async Task HistogramFormat_Test_Tags() + { + List payload = new(); + + string meterTags = "MeterTagKey=MeterTagValue,MeterTagKey2=MeterTagValue2"; + string instrumentTags = "InstrumentTagKey=InstrumentTagValue,InstrumentTagKey2=InstrumentTagValue2"; + + CounterMetadata counterInfo = new CounterMetadata(MeterName, InstrumentName, meterTags: meterTags, instrumentTags: instrumentTags, scopeHash: null); + + payload.Add(new AggregatePercentilePayload(counterInfo, "DisplayName", string.Empty, string.Empty, + new Quantile[] { new Quantile(0.5, Value1), new Quantile(0.95, Value2), new Quantile(0.99, Value3) }, + Timestamp)); + + using MemoryStream stream = await GetMetrics(payload); + List lines = ReadStream(stream); + + string metricName = $"{MeterName.ToLowerInvariant()}_{payload[0].CounterMetadata.CounterName}"; + + const string quantile_50 = "{MeterTagKey=\"MeterTagValue\", MeterTagKey2=\"MeterTagValue2\", InstrumentTagKey=\"InstrumentTagValue\", InstrumentTagKey2=\"InstrumentTagValue2\", quantile=\"0.5\"}"; + const string quantile_95 = "{MeterTagKey=\"MeterTagValue\", MeterTagKey2=\"MeterTagValue2\", InstrumentTagKey=\"InstrumentTagValue\", InstrumentTagKey2=\"InstrumentTagValue2\", quantile=\"0.95\"}"; + const string quantile_99 = "{MeterTagKey=\"MeterTagValue\", MeterTagKey2=\"MeterTagValue2\", InstrumentTagKey=\"InstrumentTagValue\", InstrumentTagKey2=\"InstrumentTagValue2\", quantile=\"0.99\"}"; + + Assert.Equal(5, lines.Count); + Assert.Equal(FormattableString.Invariant($"# HELP {metricName}{payload[0].Unit} {payload[0].DisplayName}"), lines[0]); + Assert.Equal(FormattableString.Invariant($"# TYPE {metricName} summary"), lines[1]); + Assert.Equal(FormattableString.Invariant($"{metricName}{quantile_50} {Value1}"), lines[2]); + Assert.Equal(FormattableString.Invariant($"{metricName}{quantile_95} {Value2}"), lines[3]); + Assert.Equal(FormattableString.Invariant($"{metricName}{quantile_99} {Value3}"), lines[4]); + } + [Fact] public async Task GaugeFormat_Test() { @@ -148,6 +179,30 @@ public async Task UpDownCounterFormat_Test() Assert.Equal(FormattableString.Invariant($"{metricName} {payload.Value} {new DateTimeOffset(payload.Timestamp).ToUnixTimeMilliseconds()}"), lines[2]); } + [Fact] + public async Task UpDownCounterFormat_Test_Tags() + { + string meterTags = "MeterTagKey=MeterTagValue,MeterTagKey2=MeterTagValue2"; + string instrumentTags = "InstrumentTagKey=InstrumentTagValue,InstrumentTagKey2=InstrumentTagValue2"; + string scopeHash = "123"; + + CounterMetadata counterInfo = new CounterMetadata(MeterName, InstrumentName, meterTags, instrumentTags, scopeHash); + + ICounterPayload payload = new UpDownCounterPayload(counterInfo, "DisplayName", "", null, Value1, Timestamp); + + MemoryStream stream = await GetMetrics(new() { payload }); + + List lines = ReadStream(stream); + + string metricName = $"{MeterName.ToLowerInvariant()}_{payload.CounterMetadata.CounterName}"; + string metricTags = "{MeterTagKey=\"MeterTagValue\", MeterTagKey2=\"MeterTagValue2\", InstrumentTagKey=\"InstrumentTagValue\", InstrumentTagKey2=\"InstrumentTagValue2\"}"; + + Assert.Equal(3, lines.Count); + Assert.Equal(FormattableString.Invariant($"# HELP {metricName}{payload.Unit} {payload.DisplayName}"), lines[0]); + Assert.Equal(FormattableString.Invariant($"# TYPE {metricName} gauge"), lines[1]); + Assert.Equal(FormattableString.Invariant($"{metricName}{metricTags} {payload.Value} {new DateTimeOffset(payload.Timestamp).ToUnixTimeMilliseconds()}"), lines[2]); + } + private async Task GetMetrics(List payloads) { IMetricsStore metricsStore = new MetricsStore(_logger, MetricCount);