diff --git a/src/Amazon.CloudWatch.EMF/Model/MetricDirective.cs b/src/Amazon.CloudWatch.EMF/Model/MetricDirective.cs index 53c9387..f72877f 100644 --- a/src/Amazon.CloudWatch.EMF/Model/MetricDirective.cs +++ b/src/Amazon.CloudWatch.EMF/Model/MetricDirective.cs @@ -80,6 +80,25 @@ internal List> AllDimensionKeys } } + internal void PutDimension(DimensionSet dimensionSet) + { + // Duplicate dimensions sets are removed before being added to the end of the collection. + // This ensures the latest dimension key-value is used as a target member on the root EMF node. + // This operation is O(n^2), but acceptable given sets are capped at 30 dimensions + List incomingDimensionSetKeys = dimensionSet.DimensionKeys; + CustomDimensionSets = CustomDimensionSets.Where(existingDimensionSet => + { + if (existingDimensionSet.DimensionKeys.Count != incomingDimensionSetKeys.Count) + { + return true; + } + + return !existingDimensionSet.DimensionKeys.All(existingDimensionSetKey => incomingDimensionSetKeys.Contains(existingDimensionSetKey)); + }).ToList(); + + CustomDimensionSets.Add(dimensionSet); + } + /// /// Overrides all existing dimensions, including suppressing any default dimensions. /// diff --git a/src/Amazon.CloudWatch.EMF/Model/MetricsContext.cs b/src/Amazon.CloudWatch.EMF/Model/MetricsContext.cs index b1d0ae8..44ab4a3 100644 --- a/src/Amazon.CloudWatch.EMF/Model/MetricsContext.cs +++ b/src/Amazon.CloudWatch.EMF/Model/MetricsContext.cs @@ -151,7 +151,7 @@ public object GetProperty(string name) /// the dimensions set to add. public void PutDimension(DimensionSet dimensionSet) { - _metricDirective.CustomDimensionSets.Add(dimensionSet); + _metricDirective.PutDimension(dimensionSet); } /// @@ -166,7 +166,7 @@ public void PutDimension(string dimension, string value) { var dimensionSet = new DimensionSet(); dimensionSet.AddDimension(dimension, value); - _metricDirective.CustomDimensionSets.Add(dimensionSet); + _metricDirective.PutDimension(dimensionSet); } /// diff --git a/tests/Amazon.CloudWatch.EMF.Tests/Logger/MetricsLoggerTests.cs b/tests/Amazon.CloudWatch.EMF.Tests/Logger/MetricsLoggerTests.cs index 1f6e57a..dd1efc0 100644 --- a/tests/Amazon.CloudWatch.EMF.Tests/Logger/MetricsLoggerTests.cs +++ b/tests/Amazon.CloudWatch.EMF.Tests/Logger/MetricsLoggerTests.cs @@ -93,6 +93,50 @@ public void TestOverridePreviousDimensions() Assert.Equal(dimensionValue, _sink.MetricsContext.GetAllDimensionSets()[0].GetDimensionValue(dimensionName)); } + [Fact] + public void TestPutDuplicateDimensions() + { + string dimensionName1 = "dim1"; + string dimensionName2 = "dim2"; + string dimensionValue1 = "dimValue1"; + string dimensionValue2 = "dimValue2"; + string dimensionValue3 = "dimValue3"; + string dimensionValue4 = "dimValue4"; + + _metricsLogger.PutDimensions(new DimensionSet(dimensionName1, dimensionValue1)); + _metricsLogger.PutDimensions(new DimensionSet(dimensionName2, dimensionValue2)); + _metricsLogger.PutDimensions(new DimensionSet(dimensionName1, dimensionValue3)); + _metricsLogger.PutDimensions(new DimensionSet(dimensionName2, dimensionValue4)); + _metricsLogger.Flush(); + + Assert.Equal(4, _sink.MetricsContext.GetAllDimensionSets()[0].DimensionKeys.Count); + Assert.Equal(dimensionValue3, _sink.MetricsContext.GetAllDimensionSets()[0].GetDimensionValue(dimensionName1)); + Assert.Equal(dimensionValue4, _sink.MetricsContext.GetAllDimensionSets()[0].GetDimensionValue(dimensionName2)); + } + + [Fact] + public void TestSetPutDuplicateDimensions() + { + string dimensionName1 = "dim1"; + string dimensionName2 = "dim2"; + string dimensionName3 = "dim3"; + string dimensionValue1 = "dimValue1"; + string dimensionValue2 = "dimValue2"; + string dimensionValue3 = "dimValue3"; + string dimensionValue4 = "dimValue4"; + + _metricsLogger.PutDimensions(new DimensionSet(dimensionName1, dimensionValue1)); + _metricsLogger.SetDimensions(new DimensionSet(dimensionName2, dimensionValue1)); + _metricsLogger.PutDimensions(new DimensionSet(dimensionName3, dimensionValue2)); + _metricsLogger.PutDimensions(new DimensionSet(dimensionName2, dimensionValue3)); + _metricsLogger.PutDimensions(new DimensionSet(dimensionName3, dimensionValue4)); + _metricsLogger.Flush(); + + Assert.Equal(2, _sink.MetricsContext.GetAllDimensionSets().Count); + Assert.Equal(dimensionValue3, _sink.MetricsContext.GetAllDimensionSets()[0].GetDimensionValue(dimensionName2)); + Assert.Equal(dimensionValue4, _sink.MetricsContext.GetAllDimensionSets()[1].GetDimensionValue(dimensionName3)); + } + [Fact] public void TestSetNameSpace() {