From 2b6a3367076b9fd551957a27dbab54a9eaa0cf91 Mon Sep 17 00:00:00 2001 From: Henrique <999396+hjgraca@users.noreply.github.com> Date: Wed, 9 Oct 2024 20:59:55 +0100 Subject: [PATCH 1/2] add missing array to wrap metrics array --- .../Model/MetricDirective.cs | 5 ++-- .../ClearDimensionsTests.cs | 2 +- .../EMFValidationTests.cs | 24 +++++++++---------- .../Handlers/FunctionHandlerTests.cs | 6 ++--- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricDirective.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricDirective.cs index f8ccad76..111f417f 100644 --- a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricDirective.cs +++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricDirective.cs @@ -105,7 +105,7 @@ private MetricDirective(string nameSpace, List metrics, List /// All dimension keys. [JsonPropertyName("Dimensions")] - public List AllDimensionKeys + public List> AllDimensionKeys { get { @@ -123,7 +123,8 @@ public List AllDimensionKeys if (defaultKeys.Count == 0) defaultKeys = new List(); - return defaultKeys; + // Wrap the list of strings in another list + return new List> { defaultKeys }; } } diff --git a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/ClearDimensionsTests.cs b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/ClearDimensionsTests.cs index 1ac09fbe..0a46d6fd 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/ClearDimensionsTests.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/ClearDimensionsTests.cs @@ -22,7 +22,7 @@ public void WhenClearAllDimensions_NoDimensionsInOutput() var metricsOutput = consoleOut.ToString(); // Assert - Assert.Contains("{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Metric Name\",\"Unit\":\"Count\"}],\"Dimensions\":[]", metricsOutput); + Assert.Contains("{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Metric Name\",\"Unit\":\"Count\"}],\"Dimensions\":[[]]", metricsOutput); // Reset MetricsAspect.ResetForTest(); diff --git a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/EMFValidationTests.cs b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/EMFValidationTests.cs index 79c275ae..a8d485d5 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/EMFValidationTests.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/EMFValidationTests.cs @@ -79,12 +79,12 @@ public void WhenMaxMetricsAreAdded_FlushAutomatically() // flush when it reaches MaxMetrics Assert.Contains( - "{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Metric Name 1\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 2\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 3\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 4\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 5\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 6\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 7\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 8\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 9\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 10\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 11\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 12\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 13\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 14\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 15\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 16\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 17\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 18\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 19\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 20\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 21\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 22\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 23\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 24\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 25\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 26\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 27\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 28\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 29\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 30\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 31\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 32\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 33\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 34\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 35\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 36\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 37\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 38\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 39\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 40\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 41\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 42\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 43\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 44\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 45\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 46\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 47\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 48\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 49\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 50\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 51\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 52\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 53\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 54\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 55\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 56\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 57\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 58\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 59\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 60\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 61\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 62\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 63\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 64\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 65\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 66\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 67\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 68\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 69\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 70\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 71\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 72\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 73\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 74\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 75\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 76\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 77\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 78\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 79\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 80\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 81\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 82\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 83\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 84\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 85\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 86\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 87\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 88\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 89\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 90\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 91\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 92\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 93\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 94\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 95\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 96\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 97\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 98\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 99\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 100\",\"Unit\":\"Count\"}],\"Dimensions\":[\"Service\"]", + "{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Metric Name 1\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 2\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 3\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 4\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 5\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 6\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 7\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 8\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 9\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 10\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 11\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 12\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 13\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 14\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 15\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 16\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 17\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 18\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 19\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 20\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 21\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 22\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 23\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 24\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 25\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 26\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 27\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 28\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 29\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 30\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 31\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 32\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 33\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 34\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 35\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 36\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 37\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 38\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 39\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 40\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 41\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 42\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 43\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 44\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 45\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 46\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 47\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 48\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 49\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 50\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 51\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 52\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 53\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 54\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 55\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 56\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 57\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 58\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 59\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 60\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 61\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 62\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 63\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 64\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 65\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 66\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 67\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 68\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 69\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 70\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 71\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 72\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 73\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 74\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 75\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 76\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 77\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 78\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 79\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 80\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 81\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 82\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 83\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 84\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 85\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 86\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 87\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 88\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 89\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 90\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 91\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 92\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 93\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 94\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 95\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 96\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 97\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 98\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 99\",\"Unit\":\"Count\"},{\"Name\":\"Metric Name 100\",\"Unit\":\"Count\"}],\"Dimensions\":[[\"Service\"]]", metricsOutput[0]); // flush the (MaxMetrics + 1) item only Assert.Contains( - "{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Metric Name 101\",\"Unit\":\"Count\"}],\"Dimensions\":[\"Service\"]", + "{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Metric Name 101\",\"Unit\":\"Count\"}],\"Dimensions\":[[\"Service\"]]", metricsOutput[1]); } @@ -105,7 +105,7 @@ public void WhenMaxDataPointsAreAddedToTheSameMetric_FlushAutomatically() metricsOutput[0]); // flush the (MaxMetrics + 1) item only - Assert.Contains("[\"Service\"]}]},\"Service\":\"testService\",\"Metric Name\":100}", metricsOutput[1]); + Assert.Contains("\"Dimensions\":[[\"Service\"]]}]},\"Service\":\"testService\",\"Metric Name\":100}", metricsOutput[1]); } [Trait("Category", "EMFLimits")] @@ -141,7 +141,7 @@ public void WhenDimensionsAreAdded_MustExistAsMembers() var metricsOutput = _consoleOut.ToString(); // Assert - Assert.Contains("\"Dimensions\":[\"Service\",\"functionVersion\"]" + Assert.Contains("\"Dimensions\":[[\"Service\",\"functionVersion\"]]" , metricsOutput); Assert.Contains("\"Service\":\"testService\",\"functionVersion\":\"$LATEST\"" , metricsOutput); @@ -157,11 +157,11 @@ public void When_Multiple_DimensionsAreAdded_MustExistAsMembers() var metricsOutput = _consoleOut.ToString(); // Assert - Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"ns1\",\"Metrics\":[{\"Name\":\"Lambda Execute\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[\"Type\",\"Service\"]}]},\"Type\":\"Start\",\"Service\":\"service_undefined\",\"Lambda Execute\":1}", metricsOutput); + Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"ns1\",\"Metrics\":[{\"Name\":\"Lambda Execute\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[[\"Type\",\"Service\"]]}]},\"Type\":\"Start\",\"Service\":\"service_undefined\",\"Lambda Execute\":1}", metricsOutput); - Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"ns2\",\"Metrics\":[{\"Name\":\"Lambda Execute\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[\"Type\",\"SessionId\",\"Service\"]}]},\"Type\":\"Start\",\"SessionId\":\"Unset\",\"Service\":\"service_undefined\",\"Lambda Execute\":1}", metricsOutput); + Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"ns2\",\"Metrics\":[{\"Name\":\"Lambda Execute\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[[\"Type\",\"SessionId\",\"Service\"]]}]},\"Type\":\"Start\",\"SessionId\":\"Unset\",\"Service\":\"service_undefined\",\"Lambda Execute\":1}", metricsOutput); - Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Lambda Execute\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[\"Service\",\"Default\",\"SessionId\",\"Type\"]}]},\"Service\":\"testService\",\"Default\":\"Initial\",\"SessionId\":\"MySessionId\",\"Type\":\"Start\",\"Lambda Execute\":1}", metricsOutput); + Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Lambda Execute\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[[\"Service\",\"Default\",\"SessionId\",\"Type\"]]}]},\"Service\":\"testService\",\"Default\":\"Initial\",\"SessionId\":\"MySessionId\",\"Type\":\"Start\",\"Lambda Execute\":1}", metricsOutput); } [Trait("Category", "MetricsImplementation")] @@ -209,7 +209,7 @@ public void WhenDefaultDimensionsSet_ValidInitialization() var result = _consoleOut.ToString(); // Assert - Assert.Contains($"\"Dimensions\":[\"Service\",\"{key}\"]", result); + Assert.Contains($"\"Dimensions\":[[\"Service\",\"{key}\"]]", result); Assert.Contains($"\"CustomDefaultDimension\":\"{value}\"", result); } @@ -246,7 +246,7 @@ public void WhenDefaultDimensionSet_IgnoreDuplicates() var result = _consoleOut.ToString(); // Assert - Assert.Contains("\"Dimensions\":[\"Service\",\"CustomDefaultDimension\"]", result); + Assert.Contains("\"Dimensions\":[[\"Service\",\"CustomDefaultDimension\"]]", result); Assert.Contains("\"CustomDefaultDimension\":\"CustomDefaultDimensionValue\"", result); } @@ -260,7 +260,7 @@ public void WhenMetricsAndMetadataAdded_ValidateOutput() // Assert Assert.Contains( - "CloudWatchMetrics\":[{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Time\",\"Unit\":\"Milliseconds\"}],\"Dimensions\":[\"Service\",\"functionVersion\"]}]},\"Service\":\"testService\",\"functionVersion\":\"$LATEST\",\"Time\":100.7,\"env\":\"dev\"}" + "CloudWatchMetrics\":[{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Time\",\"Unit\":\"Milliseconds\"}],\"Dimensions\":[[\"Service\",\"functionVersion\"]]}]},\"Service\":\"testService\",\"functionVersion\":\"$LATEST\",\"Time\":100.7,\"env\":\"dev\"}" , result); } @@ -275,7 +275,7 @@ public void When_Metrics_And_Metadata_Added_With_Same_Key_Should_Only_Write_Metr // Assert // No Metadata key was added Assert.Contains( - "CloudWatchMetrics\":[{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Time\",\"Unit\":\"Milliseconds\"}],\"Dimensions\":[\"Service\",\"functionVersion\"]}]},\"Service\":\"testService\",\"functionVersion\":\"$LATEST\",\"Time\":100.7}" + "CloudWatchMetrics\":[{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Time\",\"Unit\":\"Milliseconds\"}],\"Dimensions\":[[\"Service\",\"functionVersion\"]]}]},\"Service\":\"testService\",\"functionVersion\":\"$LATEST\",\"Time\":100.7}" , result); } @@ -337,7 +337,7 @@ public async Task WhenMetricsAsyncRaceConditionItemSameKeyExists_ValidateLock() // Assert Assert.Contains( - "{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Metric Name\",\"Unit\":\"Count\"}],\"Dimensions\":[\"Service\"]", + "{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Metric Name\",\"Unit\":\"Count\"}],\"Dimensions\":[[\"Service\"]]", metricsOutput); } diff --git a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandlerTests.cs b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandlerTests.cs index dd140b40..3469e2e4 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandlerTests.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandlerTests.cs @@ -85,7 +85,7 @@ public void When_LambdaContext_Should_Add_FunctioName_Dimension_CaptureColdStart metricsOutput); Assert.Contains( - "\"Metrics\":[{\"Name\":\"ColdStart\",\"Unit\":\"Count\"}],\"Dimensions\":[\"FunctionName\",\"Service\"]}]}", + "\"Metrics\":[{\"Name\":\"ColdStart\",\"Unit\":\"Count\"}],\"Dimensions\":[[\"FunctionName\",\"Service\"]]}]}", metricsOutput); } @@ -108,7 +108,7 @@ public void When_LambdaContext_And_Parameter_Should_Add_FunctioName_Dimension_Ca metricsOutput); Assert.Contains( - "\"Metrics\":[{\"Name\":\"ColdStart\",\"Unit\":\"Count\"}],\"Dimensions\":[\"FunctionName\",\"Service\"]}]}", + "\"Metrics\":[{\"Name\":\"ColdStart\",\"Unit\":\"Count\"}],\"Dimensions\":[[\"FunctionName\",\"Service\"]]}]}", metricsOutput); } @@ -125,7 +125,7 @@ public void When_No_LambdaContext_Should_Not_Add_FunctioName_Dimension_CaptureCo metricsOutput); Assert.Contains( - "\"Metrics\":[{\"Name\":\"MyMetric\",\"Unit\":\"None\"}],\"Dimensions\":[\"Service\"]}]},\"Service\":\"svc\",\"MyMetric\":1}", + "\"Metrics\":[{\"Name\":\"MyMetric\",\"Unit\":\"None\"}],\"Dimensions\":[[\"Service\"]]}]},\"Service\":\"svc\",\"MyMetric\":1}", metricsOutput); } From 31dad3b4100895b7a40a48f230877a4f9553d384 Mon Sep 17 00:00:00 2001 From: Henrique <999396+hjgraca@users.noreply.github.com> Date: Mon, 21 Oct 2024 15:39:44 +0100 Subject: [PATCH 2/2] Prevent default service to be added to PushSingleMetric --- .../AWS.Lambda.Powertools.Metrics/Metrics.cs | 78 ++++++++++++------- .../MetricsAttribute.cs | 2 +- .../EMFValidationTests.cs | 37 ++++++++- .../Handlers/FunctionHandler.cs | 38 ++++++--- 4 files changed, 110 insertions(+), 45 deletions(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Metrics.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Metrics.cs index 51b86e37..2ddbc539 100644 --- a/libraries/src/AWS.Lambda.Powertools.Metrics/Metrics.cs +++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Metrics.cs @@ -1,12 +1,12 @@ /* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * + * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at - * + * * http://aws.amazon.com/apache2.0 - * + * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing @@ -31,7 +31,7 @@ public class Metrics : IMetrics, IDisposable /// The instance /// private static IMetrics _instance; - + /// /// The context /// @@ -46,7 +46,7 @@ public class Metrics : IMetrics, IDisposable /// If true, Powertools for AWS Lambda (.NET) will throw an exception on empty metrics when trying to flush /// private readonly bool _raiseOnEmptyMetrics; - + /// /// The capture cold start enabled /// @@ -76,9 +76,8 @@ internal Metrics(IPowertoolsConfigurations powertoolsConfigurations, string name _raiseOnEmptyMetrics = raiseOnEmptyMetrics; _captureColdStartEnabled = captureColdStartEnabled; _context = InitializeContext(nameSpace, service, null); - + _powertoolsConfigurations.SetExecutionEnvironment(this); - } /// @@ -96,9 +95,11 @@ void IMetrics.AddMetric(string key, double value, MetricUnit unit, MetricResolut { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException( - nameof(key), "'AddMetric' method requires a valid metrics key. 'Null' or empty values are not allowed."); - - if (value < 0) { + nameof(key), + "'AddMetric' method requires a valid metrics key. 'Null' or empty values are not allowed."); + + if (value < 0) + { throw new ArgumentException( "'AddMetric' method requires a valid metrics value. Value must be >= 0.", nameof(value)); } @@ -106,8 +107,8 @@ void IMetrics.AddMetric(string key, double value, MetricUnit unit, MetricResolut lock (_lockObj) { var metrics = _context.GetMetrics(); - - if (metrics.Count > 0 && + + if (metrics.Count > 0 && (metrics.Count == PowertoolsConfigurations.MaxMetrics || metrics.FirstOrDefault(x => x.Name == key) ?.Values.Count == PowertoolsConfigurations.MaxMetrics)) @@ -134,7 +135,14 @@ void IMetrics.SetNamespace(string nameSpace) /// Namespace identifier string IMetrics.GetNamespace() { - return _context.GetNamespace(); + try + { + return _context.GetNamespace(); + } + catch + { + return null; + } } /// @@ -143,7 +151,14 @@ string IMetrics.GetNamespace() /// System.String. string IMetrics.GetService() { - return _context.GetService(); + try + { + return _context.GetService(); + } + catch + { + return null; + } } /// @@ -226,7 +241,7 @@ void IMetrics.Flush(bool metricsOverflow) { if (!_captureColdStartEnabled) Console.WriteLine( - "##WARNING## Metrics and Metadata have not been specified. No data will be sent to Cloudwatch Metrics."); + "##User-WARNING## No application metrics to publish. The cold-start metric may be published if enabled. If application metrics should never be empty, consider using 'RaiseOnEmptyMetrics = true'"); } } @@ -283,7 +298,7 @@ public void Dispose() Dispose(true); GC.SuppressFinalize(this); } - + /// /// /// @@ -356,7 +371,7 @@ public static void SetDefaultDimensions(Dictionary defaultDimens { _instance.SetDefaultDimensions(defaultDimensions); } - + /// /// Clears both default dimensions and dimensions lists /// @@ -389,14 +404,14 @@ private void Flush(MetricsContext context) /// Default dimensions list /// Metrics resolution public static void PushSingleMetric(string metricName, double value, MetricUnit unit, string nameSpace = null, - string service = null, Dictionary defaultDimensions = null, MetricResolution metricResolution = MetricResolution.Default) + string service = null, Dictionary defaultDimensions = null, + MetricResolution metricResolution = MetricResolution.Default) { _instance.PushSingleMetric(metricName, value, unit, nameSpace, service, defaultDimensions, metricResolution); } /// - /// Sets global namespace, service name and default dimensions list. Service name is automatically added as a default - /// dimension + /// Sets global namespace, service name and default dimensions list. /// /// Metrics namespace /// Service Name @@ -406,19 +421,26 @@ private MetricsContext InitializeContext(string nameSpace, string service, Dictionary defaultDimensions) { var context = new MetricsContext(); + var defaultDimensionsList = DictionaryToList(defaultDimensions); context.SetNamespace(!string.IsNullOrWhiteSpace(nameSpace) ? nameSpace - : _powertoolsConfigurations.MetricsNamespace); + : _instance.GetNamespace() ?? _powertoolsConfigurations.MetricsNamespace); - context.SetService(!string.IsNullOrWhiteSpace(service) + // this needs to check if service is set through code or env variables + // the default value service_undefined has to be ignored and return null so it is not added as default + // TODO: Check if there is a way to get the default dimensions and if it makes sense + var parsedService = !string.IsNullOrWhiteSpace(service) ? service - : _powertoolsConfigurations.Service); - - var defaultDimensionsList = DictionaryToList(defaultDimensions); + : _powertoolsConfigurations.Service == "service_undefined" + ? null + : _powertoolsConfigurations.Service; - // Add service as a default dimension - defaultDimensionsList.Add(new DimensionSet("Service", context.GetService())); + if (parsedService != null) + { + context.SetService(parsedService); + defaultDimensionsList.Add(new DimensionSet("Service", context.GetService())); + } context.SetDefaultDimensions(defaultDimensionsList); @@ -447,4 +469,4 @@ internal static void ResetForTest() { _instance = null; } -} +} \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/MetricsAttribute.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/MetricsAttribute.cs index 761bf7bd..0033f560 100644 --- a/libraries/src/AWS.Lambda.Powertools.Metrics/MetricsAttribute.cs +++ b/libraries/src/AWS.Lambda.Powertools.Metrics/MetricsAttribute.cs @@ -66,7 +66,7 @@ namespace AWS.Lambda.Powertools.Metrics; /// /// /// Service -/// string, service name is used for metric dimension across all metrics, by default service_undefined +/// string, service name is used for metric dimension /// /// /// Namespace diff --git a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/EMFValidationTests.cs b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/EMFValidationTests.cs index a8d485d5..0be19d3b 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/EMFValidationTests.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/EMFValidationTests.cs @@ -157,11 +157,39 @@ public void When_Multiple_DimensionsAreAdded_MustExistAsMembers() var metricsOutput = _consoleOut.ToString(); // Assert - Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"ns1\",\"Metrics\":[{\"Name\":\"Lambda Execute\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[[\"Type\",\"Service\"]]}]},\"Type\":\"Start\",\"Service\":\"service_undefined\",\"Lambda Execute\":1}", metricsOutput); - - Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"ns2\",\"Metrics\":[{\"Name\":\"Lambda Execute\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[[\"Type\",\"SessionId\",\"Service\"]]}]},\"Type\":\"Start\",\"SessionId\":\"Unset\",\"Service\":\"service_undefined\",\"Lambda Execute\":1}", metricsOutput); + Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"ColdStart\",\"Unit\":\"Count\"}],\"Dimensions\":[[\"Service\"]]}]},\"Service\":\"ServiceName\",\"ColdStart\":1}", metricsOutput); + Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"SingleMetric1\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[[\"Default1\"]]}]},\"Default1\":\"SingleMetric1\",\"SingleMetric1\":1}", metricsOutput); + Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"ns2\",\"Metrics\":[{\"Name\":\"SingleMetric2\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[[\"Default1\",\"Default2\"]]}]},\"Default1\":\"SingleMetric2\",\"Default2\":\"SingleMetric2\",\"SingleMetric2\":1}", metricsOutput); + Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"AddMetric\",\"Unit\":\"Count\",\"StorageResolution\":1},{\"Name\":\"AddMetric2\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[[\"Service\"]]}]},\"Service\":\"ServiceName\",\"AddMetric\":1,\"AddMetric2\":1}", metricsOutput); + } + + [Trait("Category", "SchemaValidation")] + [Fact] + public void When_PushSingleMetric_With_Namespace() + { + // Act + _handler.PushSingleMetricWithNamespace(); + + var metricsOutput = _consoleOut.ToString(); + + // Assert + Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"ExampleApplication\",\"Metrics\":[{\"Name\":\"SingleMetric\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[[\"Default\"]]}]},\"Default\":\"SingleMetric\",\"SingleMetric\":1}", metricsOutput); + } + + [Trait("Category", "SchemaValidation")] + [Fact] + public void When_PushSingleMetric_With_Env_Namespace() + { + // Arrange + Environment.SetEnvironmentVariable("POWERTOOLS_METRICS_NAMESPACE", "EnvNamespace"); - Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Lambda Execute\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[[\"Service\",\"Default\",\"SessionId\",\"Type\"]]}]},\"Service\":\"testService\",\"Default\":\"Initial\",\"SessionId\":\"MySessionId\",\"Type\":\"Start\",\"Lambda Execute\":1}", metricsOutput); + // Act + _handler.PushSingleMetricWithEnvNamespace(); + + var metricsOutput = _consoleOut.ToString(); + + // Assert + Assert.Contains("\"CloudWatchMetrics\":[{\"Namespace\":\"EnvNamespace\",\"Metrics\":[{\"Name\":\"SingleMetric\",\"Unit\":\"Count\",\"StorageResolution\":1}],\"Dimensions\":[[\"Default\"]]}]},\"Default\":\"SingleMetric\",\"SingleMetric\":1}", metricsOutput); } [Trait("Category", "MetricsImplementation")] @@ -366,6 +394,7 @@ public void Dispose() { // need to reset instance after each test MetricsAspect.ResetForTest(); + Environment.SetEnvironmentVariable("POWERTOOLS_METRICS_NAMESPACE", null); } } } \ No newline at end of file diff --git a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandler.cs b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandler.cs index e29e99a9..f00a8c5f 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandler.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandler.cs @@ -39,25 +39,39 @@ public void AddDimensions() Metrics.AddMetric("TestMetric", 1, MetricUnit.Count); } - [Metrics(Namespace = "dotnet-powertools-test", Service = "testService")] + [Metrics(Namespace = "dotnet-powertools-test", Service = "ServiceName", CaptureColdStart = true)] public void AddMultipleDimensions() { - Metrics.SetDefaultDimensions(new Dictionary { - { "Default", "Initial" } - }); - Metrics.PushSingleMetric("Lambda Execute", 1, MetricUnit.Count, metricResolution: MetricResolution.High, nameSpace: "ns1", + Metrics.PushSingleMetric("SingleMetric1", 1, MetricUnit.Count, metricResolution: MetricResolution.High, defaultDimensions: new Dictionary { - { "Type", "Start" } + { "Default1", "SingleMetric1" } }); - Metrics.PushSingleMetric("Lambda Execute", 1, MetricUnit.Count, metricResolution: MetricResolution.High, nameSpace: "ns2", + Metrics.PushSingleMetric("SingleMetric2", 1, MetricUnit.Count, metricResolution: MetricResolution.High, nameSpace: "ns2", + defaultDimensions: new Dictionary { + { "Default1", "SingleMetric2" }, + { "Default2", "SingleMetric2" } + }); + Metrics.AddMetric("AddMetric", 1, MetricUnit.Count, MetricResolution.High); + Metrics.AddMetric("AddMetric2", 1, MetricUnit.Count, MetricResolution.High); + } + + [Metrics(Namespace = "ExampleApplication")] + public void PushSingleMetricWithNamespace() + { + Metrics.PushSingleMetric("SingleMetric", 1, MetricUnit.Count, metricResolution: MetricResolution.High, + defaultDimensions: new Dictionary { + { "Default", "SingleMetric" } + }); + } + + [Metrics] + public void PushSingleMetricWithEnvNamespace() + { + Metrics.PushSingleMetric("SingleMetric", 1, MetricUnit.Count, metricResolution: MetricResolution.High, defaultDimensions: new Dictionary { - { "Type", "Start" }, - { "SessionId", "Unset" } + { "Default", "SingleMetric" } }); - Metrics.AddMetric("Lambda Execute", 1, MetricUnit.Count, MetricResolution.High); - Metrics.AddDimension("SessionId", "MySessionId"); - Metrics.AddDimension("Type", "Start"); } [Metrics(Namespace = "dotnet-powertools-test", Service = "testService")]