diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/AWS.Lambda.Powertools.Metrics.csproj b/libraries/src/AWS.Lambda.Powertools.Metrics/AWS.Lambda.Powertools.Metrics.csproj
index 0e90e99b..e20deb7e 100644
--- a/libraries/src/AWS.Lambda.Powertools.Metrics/AWS.Lambda.Powertools.Metrics.csproj
+++ b/libraries/src/AWS.Lambda.Powertools.Metrics/AWS.Lambda.Powertools.Metrics.csproj
@@ -11,4 +11,8 @@
+
+
+
+
diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Internal/MetricsAspect.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Internal/MetricsAspect.cs
index abbefc5f..a72e205e 100644
--- a/libraries/src/AWS.Lambda.Powertools.Metrics/Internal/MetricsAspect.cs
+++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Internal/MetricsAspect.cs
@@ -17,6 +17,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using Amazon.Lambda.Core;
using AspectInjector.Broker;
using AWS.Lambda.Powertools.Common;
@@ -34,11 +35,6 @@ public class MetricsAspect
///
private static bool _isColdStart;
- ///
- /// Specify to clear Lambda Context on exit
- ///
- private bool _clearLambdaContext;
-
///
/// Gets the metrics instance.
///
@@ -100,14 +96,14 @@ public void Before(
var nameSpace = _metricsInstance.GetNamespace();
var service = _metricsInstance.GetService();
Dictionary dimensions = null;
-
- _clearLambdaContext = PowertoolsLambdaContext.Extract(eventArgs);
-
- if (PowertoolsLambdaContext.Instance is not null)
+
+ var context = GetContext(eventArgs);
+
+ if (context is not null)
{
dimensions = new Dictionary
{
- { "FunctionName", PowertoolsLambdaContext.Instance.FunctionName }
+ { "FunctionName", context.FunctionName }
};
}
@@ -129,8 +125,6 @@ public void Before(
public void Exit()
{
_metricsInstance.Flush();
- if (_clearLambdaContext)
- PowertoolsLambdaContext.Clear();
}
@@ -142,6 +136,21 @@ internal static void ResetForTest()
_metricsInstance = null;
_isColdStart = true;
Metrics.ResetForTest();
- PowertoolsLambdaContext.Clear();
+ }
+
+ ///
+ /// Gets the Lambda context
+ ///
+ ///
+ ///
+ private static ILambdaContext GetContext(AspectEventArgs args)
+ {
+ var index = Array.FindIndex(args.Method.GetParameters(), p => p.ParameterType == typeof(ILambdaContext));
+ if (index >= 0)
+ {
+ return (ILambdaContext)args.Args[index];
+ }
+
+ return null;
}
}
\ No newline at end of file
diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricResolution.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricResolution.cs
index 2112c1c5..3929beec 100644
--- a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricResolution.cs
+++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricResolution.cs
@@ -1,4 +1,3 @@
-using System.Runtime.Serialization;
using System.Text.Json.Serialization;
namespace AWS.Lambda.Powertools.Metrics;
@@ -6,6 +5,7 @@ namespace AWS.Lambda.Powertools.Metrics;
///
/// Enum MetricResolution
///
+[JsonConverter(typeof(MetricResolutionJsonConverter))]
public enum MetricResolution
{
///
diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricUnit.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricUnit.cs
index 132b10f3..2fbb389d 100644
--- a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricUnit.cs
+++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricUnit.cs
@@ -24,7 +24,7 @@ namespace AWS.Lambda.Powertools.Metrics;
#if NET8_0_OR_GREATER
[JsonConverter(typeof(JsonStringEnumConverter))]
#else
-[JsonConverter(typeof(StringEnumConverter))]
+[JsonConverter(typeof(JsonStringEnumConverter))]
#endif
public enum MetricUnit
{
diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/MetricResolutionJsonConverter.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/MetricResolutionJsonConverter.cs
new file mode 100644
index 00000000..710b1a2a
--- /dev/null
+++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/MetricResolutionJsonConverter.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace AWS.Lambda.Powertools.Metrics;
+
+///
+/// Class MetricResolutionJsonConverter.
+/// Implements the
+///
+///
+public class MetricResolutionJsonConverter : JsonConverter
+{
+ ///
+ /// Reads the JSON representation of the object.
+ ///
+ /// The to read from.
+ /// The being converted.
+ /// The being used.
+ /// The object value.
+ public override MetricResolution Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ if (reader.TokenType == JsonTokenType.String)
+ {
+ var stringValue = reader.GetString();
+ if (int.TryParse(stringValue, out int value))
+ {
+ return (MetricResolution)value;
+ }
+ }
+ else if (reader.TokenType == JsonTokenType.Number)
+ {
+ return (MetricResolution)reader.GetInt32();
+ }
+
+ throw new JsonException();
+ }
+
+ ///
+ /// Writes the JSON representation of the object.
+ ///
+ /// The to write to.
+ /// The value to convert.
+ /// The being used.
+ public override void Write(Utf8JsonWriter writer, MetricResolution value, JsonSerializerOptions options)
+ {
+ writer.WriteNumberValue((int)value);
+ }
+}
\ No newline at end of file
diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/StringEnumConverter.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/StringEnumConverter.cs
deleted file mode 100644
index 242ee90b..00000000
--- a/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/StringEnumConverter.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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
- * permissions and limitations under the License.
- */
-
-using System;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.Serialization;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace AWS.Lambda.Powertools.Metrics;
-
-#if NET6_0
-
-///
-/// Class StringEnumConverter.
-/// Implements the
-/// .NET 6 only
-///
-///
-public class StringEnumConverter : JsonConverterFactory
-{
- ///
- /// The allow integer values
- ///
- private readonly bool _allowIntegerValues;
-
- ///
- /// The base converter
- ///
- private readonly JsonStringEnumConverter _baseConverter;
-
- ///
- /// The naming policy
- ///
- private readonly JsonNamingPolicy _namingPolicy;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public StringEnumConverter() : this(null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The naming policy.
- /// if set to true [allow integer values].
- private StringEnumConverter(JsonNamingPolicy namingPolicy = null, bool allowIntegerValues = true)
- {
- _namingPolicy = namingPolicy;
- _allowIntegerValues = allowIntegerValues;
- _baseConverter = new JsonStringEnumConverter(namingPolicy, allowIntegerValues);
- }
-
- ///
- /// When overridden in a derived class, determines whether the converter instance can convert the specified object
- /// type.
- ///
- /// The type of the object to check whether it can be converted by this converter instance.
- ///
- /// if the instance can convert the specified object type; otherwise,
- /// .
- ///
- public override bool CanConvert(Type typeToConvert)
- {
- return _baseConverter.CanConvert(typeToConvert);
- }
-
- ///
- /// Creates a converter for a specified type.
- ///
- /// The type handled by the converter.
- /// The serialization options to use.
- /// A converter for which type is compatible with .
- public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
- {
- var query = from field in typeToConvert.GetFields(BindingFlags.Public | BindingFlags.Static)
- let attr = field.GetCustomAttribute()
- where attr != null
- select (field.Name, attr.Value);
- var dictionary = query.ToDictionary(p => p.Item1, p => p.Item2);
- return dictionary.Count > 0
- ? new JsonStringEnumConverter(new DictionaryLookupNamingPolicy(dictionary, _namingPolicy),
- _allowIntegerValues).CreateConverter(typeToConvert, options)
- : _baseConverter.CreateConverter(typeToConvert, options);
- }
-}
-#endif
\ 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 8ae59b9f..8447575d 100644
--- a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandler.cs
+++ b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandler.cs
@@ -169,8 +169,14 @@ public void HandleWithLambdaContext(ILambdaContext context)
}
[Metrics(Namespace = "ns", Service = "svc")]
- public void HandleWithLambdaContextAndMetrics(TestLambdaContext context)
+ public void HandleColdStartNoContext()
{
Metrics.AddMetric("MyMetric", 1);
}
+
+ [Metrics(Namespace = "ns", Service = "svc", CaptureColdStart = true)]
+ public void HandleWithParamAndLambdaContext(string input, ILambdaContext context)
+ {
+
+ }
}
\ No newline at end of file
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 556d6cce..075da0a0 100644
--- a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandlerTests.cs
+++ b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandlerTests.cs
@@ -88,6 +88,46 @@ public void When_LambdaContext_Should_Add_FunctioName_Dimension_CaptureColdStart
"\"Metrics\":[{\"Name\":\"ColdStart\",\"Unit\":\"Count\"}],\"Dimensions\":[[\"FunctionName\"],[\"Service\"]]}]}",
metricsOutput);
}
+
+ [Fact]
+ public void When_LambdaContext_And_Parameter_Should_Add_FunctioName_Dimension_CaptureColdStart()
+ {
+ // Arrange
+ var context = new TestLambdaContext
+ {
+ FunctionName = "My Function with context"
+ };
+
+ // Act
+ _handler.HandleWithParamAndLambdaContext("Hello",context);
+ var metricsOutput = _consoleOut.ToString();
+
+ // Assert
+ Assert.Contains(
+ "\"FunctionName\":\"My Function with context\"",
+ metricsOutput);
+
+ Assert.Contains(
+ "\"Metrics\":[{\"Name\":\"ColdStart\",\"Unit\":\"Count\"}],\"Dimensions\":[[\"FunctionName\"],[\"Service\"]]}]}",
+ metricsOutput);
+ }
+
+ [Fact]
+ public void When_No_LambdaContext_Should_Not_Add_FunctioName_Dimension_CaptureColdStart()
+ {
+ // Act
+ _handler.HandleColdStartNoContext();
+ var metricsOutput = _consoleOut.ToString();
+
+ // Assert
+ Assert.DoesNotContain(
+ "\"FunctionName\"",
+ metricsOutput);
+
+ Assert.Contains(
+ "\"Metrics\":[{\"Name\":\"MyMetric\",\"Unit\":\"None\"}],\"Dimensions\":[[\"Service\"]]}]},\"Service\":\"svc\",\"MyMetric\":1}",
+ metricsOutput);
+ }
public void Dispose()
{
diff --git a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/SerializationTests.cs b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/SerializationTests.cs
new file mode 100644
index 00000000..2433c5a2
--- /dev/null
+++ b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/SerializationTests.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Text.Json;
+using Xunit;
+
+namespace AWS.Lambda.Powertools.Metrics.Tests;
+
+[Collection("Sequential")]
+public class SerializationTests
+{
+ [Fact]
+ public void Metrics_Resolution_JsonConverter()
+ {
+ // Arrange
+ var options = new JsonSerializerOptions();
+ options.Converters.Add(new MetricResolutionJsonConverter());
+
+ {
+ var myInt = JsonSerializer.Deserialize(1, options);
+ Assert.Equal(MetricResolution.High, myInt);
+ Assert.Equal("1", JsonSerializer.Serialize(myInt, options));
+ }
+
+ {
+ var myInt = JsonSerializer.Deserialize("1", options);
+ Assert.Equal(MetricResolution.High, myInt);
+ Assert.Equal("1", JsonSerializer.Serialize(myInt, options));
+ }
+
+ {
+ var myInt = JsonSerializer.Deserialize("60", options);
+ Assert.Equal(MetricResolution.Standard, myInt);
+ Assert.Equal("60", JsonSerializer.Serialize(myInt, options));
+ }
+
+ {
+ var myInt = JsonSerializer.Deserialize("0", options);
+ Assert.Equal(MetricResolution.Default, myInt);
+ Assert.Equal("0", JsonSerializer.Serialize(myInt, options));
+ }
+
+ {
+ var myInt = JsonSerializer.Deserialize(@"""1""", options);
+ Assert.Equal(MetricResolution.High, myInt);
+ Assert.Equal("1", JsonSerializer.Serialize(myInt, options));
+ }
+ {
+ var myInt = JsonSerializer.Deserialize(@"""60""", options);
+ Assert.Equal(MetricResolution.Standard, myInt);
+ Assert.Equal("60", JsonSerializer.Serialize(myInt, options));
+ }
+ {
+ var myInt = JsonSerializer.Deserialize(@"""0""", options);
+ Assert.Equal(MetricResolution.Default, myInt);
+ Assert.Equal("0", JsonSerializer.Serialize(myInt, options));
+ }
+ }
+
+ [Fact]
+ public void Metrics_Resolution_JsonConverter_Exception()
+ {
+ // Arrange
+ var options = new JsonSerializerOptions();
+ options.Converters.Add(new MetricResolutionJsonConverter());
+
+ {
+ Action act = () => JsonSerializer.Deserialize("1.3", options);
+ Assert.Throws(act);
+ }
+
+ {
+ Action act = () => JsonSerializer.Deserialize(@"""1.3""", options);
+ Assert.Throws(act);
+ }
+
+ {
+ Action act = () => JsonSerializer.Deserialize(@"""abc""", options);
+ Assert.Throws(act);
+ }
+ }
+}
\ No newline at end of file
diff --git a/version.json b/version.json
index ec7a6148..9fb16922 100644
--- a/version.json
+++ b/version.json
@@ -1,7 +1,7 @@
{
"Core": {
"Logging": "1.5.1",
- "Metrics": "1.7.0",
+ "Metrics": "1.7.1",
"Tracing": "1.4.2"
},
"Utilities": {