From 44ae98fbbaca3c753e90947c88dda75367e422ad Mon Sep 17 00:00:00 2001
From: Henrique Graca <999396+hjgraca@users.noreply.github.com>
Date: Mon, 20 May 2024 11:21:30 +0100
Subject: [PATCH 1/2] add thread safety test. AddMetric lock.
---
.../AWS.Lambda.Powertools.Metrics/Metrics.cs | 26 ++++++++++++-------
.../Handlers/FunctionHandler.cs | 15 +++++++++++
.../Handlers/FunctionHandlerTests.cs | 12 +++++++++
3 files changed, 44 insertions(+), 9 deletions(-)
diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Metrics.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Metrics.cs
index af72bd89..51b86e37 100644
--- a/libraries/src/AWS.Lambda.Powertools.Metrics/Metrics.cs
+++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Metrics.cs
@@ -52,6 +52,11 @@ public class Metrics : IMetrics, IDisposable
///
private readonly bool _captureColdStartEnabled;
+ //
+ // Shared synchronization object
+ //
+ private readonly object _lockObj = new();
+
///
/// Creates a Metrics object that provides features to send metrics to Amazon Cloudwatch using the Embedded metric
/// format (EMF). See
@@ -98,17 +103,20 @@ void IMetrics.AddMetric(string key, double value, MetricUnit unit, MetricResolut
"'AddMetric' method requires a valid metrics value. Value must be >= 0.", nameof(value));
}
- var metrics = _context.GetMetrics();
-
- if (metrics.Count > 0 &&
- (metrics.Count == PowertoolsConfigurations.MaxMetrics ||
- metrics.FirstOrDefault(x => x.Name == key)
- ?.Values.Count == PowertoolsConfigurations.MaxMetrics))
+ lock (_lockObj)
{
- _instance.Flush(true);
+ var metrics = _context.GetMetrics();
+
+ if (metrics.Count > 0 &&
+ (metrics.Count == PowertoolsConfigurations.MaxMetrics ||
+ metrics.FirstOrDefault(x => x.Name == key)
+ ?.Values.Count == PowertoolsConfigurations.MaxMetrics))
+ {
+ _instance.Flush(true);
+ }
+
+ _context.AddMetric(key, value, unit, metricResolution);
}
-
- _context.AddMetric(key, value, unit, metricResolution);
}
///
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 50bb050f..c781731d 100644
--- a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandler.cs
+++ b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandler.cs
@@ -13,8 +13,11 @@
* permissions and limitations under the License.
*/
+using System;
using System.Globalization;
+using System.Linq;
using System.Threading.Tasks;
+using AWS.Lambda.Powertools.Common;
namespace AWS.Lambda.Powertools.Metrics.Tests.Handlers;
@@ -41,4 +44,16 @@ public async Task HandleTestSecondCall(string input)
return input.ToUpper(CultureInfo.InvariantCulture);
}
+
+ [Metrics(Namespace = "ns", Service = "svc")]
+ public async Task HandleMultipleThreads(string input)
+ {
+ await Parallel.ForEachAsync(Enumerable.Range(0, Environment.ProcessorCount * 2), async (x, _) =>
+ {
+ Metrics.AddMetric("MyMetric", 1);
+ await Task.Delay(1);
+ });
+
+ return input.ToUpper(CultureInfo.InvariantCulture);
+ }
}
\ 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 9531e3c9..4afba753 100644
--- a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandlerTests.cs
+++ b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandlerTests.cs
@@ -49,4 +49,16 @@ public async Task When_Metrics_Add_Metadata_Second_Invocation_Should_Not_Throw_E
exception = await Record.ExceptionAsync( () => handler.HandleTestSecondCall("whatever"));
Assert.Null(exception);
}
+
+ [Fact]
+ public async Task When_Metrics_Add_Metadata_FromMultipleThread_Should_Not_Throw_Exception()
+ {
+ // Arrange
+ Metrics.ResetForTest();
+ var handler = new FunctionHandler();
+
+ // Act
+ var exception = await Record.ExceptionAsync(() => handler.HandleMultipleThreads("whatever"));
+ Assert.Null(exception);
+ }
}
\ No newline at end of file
From ab95e85e61cbf8ed934e78dc56122dadb18af3e9 Mon Sep 17 00:00:00 2001
From: Henrique Graca <999396+hjgraca@users.noreply.github.com>
Date: Mon, 20 May 2024 11:33:46 +0100
Subject: [PATCH 2/2] remove unused
---
.../Handlers/FunctionHandler.cs | 1 -
1 file changed, 1 deletion(-)
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 c781731d..271b2e21 100644
--- a/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandler.cs
+++ b/libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/Handlers/FunctionHandler.cs
@@ -17,7 +17,6 @@
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
-using AWS.Lambda.Powertools.Common;
namespace AWS.Lambda.Powertools.Metrics.Tests.Handlers;