Add unit test to check that metric dimensions are order insensitive (#2788)

This commit is contained in:
Utkarsh Umesan Pillai 2022-01-18 16:27:10 -08:00 committed by GitHub
parent fcb6b40bfa
commit d4cf69301d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 217 additions and 0 deletions

View File

@ -382,6 +382,188 @@ namespace OpenTelemetry.Metrics.Tests
}
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void DimensionsAreOrderInsensitiveWithSortedKeysFirst(bool exportDelta)
{
var exportedItems = new List<Metric>();
using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{exportDelta}");
var counterLong = meter.CreateCounter<long>("Counter");
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(meter.Name)
.AddReader(new BaseExportingMetricReader(new InMemoryExporter<Metric>(exportedItems))
{
Temporality = exportDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative,
})
.Build();
// Emit the first metric with the sorted order of tag keys
counterLong.Add(5, new("Key1", "Value1"), new("Key2", "Value2"), new("Key3", "Value3"));
counterLong.Add(10, new("Key1", "Value1"), new("Key3", "Value3"), new("Key2", "Value2"));
counterLong.Add(10, new("Key2", "Value20"), new("Key1", "Value10"), new("Key3", "Value30"));
// Emit a metric with different set of keys but the same set of values as one of the previous metric points
counterLong.Add(25, new("Key4", "Value1"), new("Key5", "Value3"), new("Key6", "Value2"));
counterLong.Add(25, new("Key4", "Value1"), new("Key6", "Value3"), new("Key5", "Value2"));
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
List<KeyValuePair<string, object>> expectedTagsForFirstMetricPoint = new List<KeyValuePair<string, object>>()
{
new("Key1", "Value1"),
new("Key2", "Value2"),
new("Key3", "Value3"),
};
List<KeyValuePair<string, object>> expectedTagsForSecondMetricPoint = new List<KeyValuePair<string, object>>()
{
new("Key1", "Value10"),
new("Key2", "Value20"),
new("Key3", "Value30"),
};
List<KeyValuePair<string, object>> expectedTagsForThirdMetricPoint = new List<KeyValuePair<string, object>>()
{
new("Key4", "Value1"),
new("Key5", "Value3"),
new("Key6", "Value2"),
};
List<KeyValuePair<string, object>> expectedTagsForFourthMetricPoint = new List<KeyValuePair<string, object>>()
{
new("Key4", "Value1"),
new("Key5", "Value2"),
new("Key6", "Value3"),
};
Assert.Equal(4, GetNumberOfMetricPoints(exportedItems));
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForFirstMetricPoint, 1);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForSecondMetricPoint, 2);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForThirdMetricPoint, 3);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForFourthMetricPoint, 4);
long sumReceived = GetLongSum(exportedItems);
Assert.Equal(75, sumReceived);
exportedItems.Clear();
counterLong.Add(5, new("Key2", "Value2"), new("Key1", "Value1"), new("Key3", "Value3"));
counterLong.Add(5, new("Key2", "Value2"), new("Key1", "Value1"), new("Key3", "Value3"));
counterLong.Add(10, new("Key2", "Value2"), new("Key3", "Value3"), new("Key1", "Value1"));
counterLong.Add(10, new("Key2", "Value20"), new("Key3", "Value30"), new("Key1", "Value10"));
counterLong.Add(20, new("Key4", "Value1"), new("Key6", "Value2"), new("Key5", "Value3"));
counterLong.Add(20, new("Key4", "Value1"), new("Key5", "Value2"), new("Key6", "Value3"));
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Equal(4, GetNumberOfMetricPoints(exportedItems));
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForFirstMetricPoint, 1);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForSecondMetricPoint, 2);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForThirdMetricPoint, 3);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForFourthMetricPoint, 4);
sumReceived = GetLongSum(exportedItems);
if (exportDelta)
{
Assert.Equal(70, sumReceived);
}
else
{
Assert.Equal(145, sumReceived);
}
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void DimensionsAreOrderInsensitiveWithUnsortedKeysFirst(bool exportDelta)
{
var exportedItems = new List<Metric>();
using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{exportDelta}");
var counterLong = meter.CreateCounter<long>("Counter");
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(meter.Name)
.AddReader(new BaseExportingMetricReader(new InMemoryExporter<Metric>(exportedItems))
{
Temporality = exportDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative,
})
.Build();
// Emit the first metric with the unsorted order of tag keys
counterLong.Add(5, new("Key1", "Value1"), new("Key3", "Value3"), new("Key2", "Value2"));
counterLong.Add(10, new("Key1", "Value1"), new("Key2", "Value2"), new("Key3", "Value3"));
counterLong.Add(10, new("Key2", "Value20"), new("Key1", "Value10"), new("Key3", "Value30"));
// Emit a metric with different set of keys but the same set of values as one of the previous metric points
counterLong.Add(25, new("Key4", "Value1"), new("Key5", "Value3"), new("Key6", "Value2"));
counterLong.Add(25, new("Key4", "Value1"), new("Key6", "Value3"), new("Key5", "Value2"));
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
List<KeyValuePair<string, object>> expectedTagsForFirstMetricPoint = new List<KeyValuePair<string, object>>()
{
new("Key1", "Value1"),
new("Key2", "Value2"),
new("Key3", "Value3"),
};
List<KeyValuePair<string, object>> expectedTagsForSecondMetricPoint = new List<KeyValuePair<string, object>>()
{
new("Key1", "Value10"),
new("Key2", "Value20"),
new("Key3", "Value30"),
};
List<KeyValuePair<string, object>> expectedTagsForThirdMetricPoint = new List<KeyValuePair<string, object>>()
{
new("Key4", "Value1"),
new("Key5", "Value3"),
new("Key6", "Value2"),
};
List<KeyValuePair<string, object>> expectedTagsForFourthMetricPoint = new List<KeyValuePair<string, object>>()
{
new("Key4", "Value1"),
new("Key5", "Value2"),
new("Key6", "Value3"),
};
Assert.Equal(4, GetNumberOfMetricPoints(exportedItems));
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForFirstMetricPoint, 1);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForSecondMetricPoint, 2);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForThirdMetricPoint, 3);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForFourthMetricPoint, 4);
long sumReceived = GetLongSum(exportedItems);
Assert.Equal(75, sumReceived);
exportedItems.Clear();
counterLong.Add(5, new("Key2", "Value2"), new("Key1", "Value1"), new("Key3", "Value3"));
counterLong.Add(5, new("Key2", "Value2"), new("Key1", "Value1"), new("Key3", "Value3"));
counterLong.Add(10, new("Key2", "Value2"), new("Key3", "Value3"), new("Key1", "Value1"));
counterLong.Add(10, new("Key2", "Value20"), new("Key3", "Value30"), new("Key1", "Value10"));
counterLong.Add(20, new("Key4", "Value1"), new("Key6", "Value2"), new("Key5", "Value3"));
counterLong.Add(20, new("Key4", "Value1"), new("Key5", "Value2"), new("Key6", "Value3"));
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Equal(4, GetNumberOfMetricPoints(exportedItems));
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForFirstMetricPoint, 1);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForSecondMetricPoint, 2);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForThirdMetricPoint, 3);
CheckTagsForNthMetricPoint(exportedItems, expectedTagsForFourthMetricPoint, 4);
sumReceived = GetLongSum(exportedItems);
if (exportDelta)
{
Assert.Equal(70, sumReceived);
}
else
{
Assert.Equal(145, sumReceived);
}
}
[Theory]
[InlineData(AggregationTemporality.Cumulative)]
[InlineData(AggregationTemporality.Delta)]
@ -658,6 +840,41 @@ namespace OpenTelemetry.Metrics.Tests
return sum;
}
private static int GetNumberOfMetricPoints(List<Metric> metrics)
{
int count = 0;
foreach (var metric in metrics)
{
foreach (ref readonly var metricPoint in metric.GetMetricPoints())
{
count++;
}
}
return count;
}
// Provide tags input sorted by Key
private static void CheckTagsForNthMetricPoint(List<Metric> metrics, List<KeyValuePair<string, object>> tags, int n)
{
var metric = metrics[0];
var metricPointEnumerator = metric.GetMetricPoints().GetEnumerator();
for (int i = 0; i < n; i++)
{
Assert.True(metricPointEnumerator.MoveNext());
}
int index = 0;
var metricPoint = metricPointEnumerator.Current;
foreach (var tag in metricPoint.Tags)
{
Assert.Equal(tags[index].Key, tag.Key);
Assert.Equal(tags[index].Value, tag.Value);
index++;
}
}
private static void CounterUpdateThread<T>(object obj)
where T : struct, IComparable
{