Skip to content

Commit 7ea9051

Browse files
authored
Merge pull request #313 from hjgraca/metrics-addmetric-raceconditiom
2 parents 6a46c4e + 9a34c30 commit 7ea9051

File tree

2 files changed

+60
-5
lines changed

2 files changed

+60
-5
lines changed

libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricDirective.cs

+13-5
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ public List<List<string>> AllDimensionKeys
126126
return defaultKeys;
127127
}
128128
}
129+
130+
/// <summary>
131+
/// Shared synchronization object
132+
/// </summary>
133+
private readonly object _lockObj = new();
129134

130135
/// <summary>
131136
/// Adds metric to memory
@@ -139,11 +144,14 @@ public void AddMetric(string name, double value, MetricUnit unit, MetricResoluti
139144
{
140145
if (Metrics.Count < PowertoolsConfigurations.MaxMetrics)
141146
{
142-
var metric = Metrics.FirstOrDefault(m => m.Name == name);
143-
if (metric != null)
144-
metric.AddValue(value);
145-
else
146-
Metrics.Add(new MetricDefinition(name, unit, value, metricResolution));
147+
lock (_lockObj)
148+
{
149+
var metric = Metrics.FirstOrDefault(m => m.Name == name);
150+
if (metric != null)
151+
metric.AddValue(value);
152+
else
153+
Metrics.Add(new MetricDefinition(name, unit, value, metricResolution));
154+
}
147155
}
148156
else
149157
{

libraries/tests/AWS.Lambda.Powertools.Metrics.Tests/EMFValidationTests.cs

+47
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using System;
1717
using System.Collections.Generic;
1818
using System.IO;
19+
using System.Threading.Tasks;
1920
using AWS.Lambda.Powertools.Common;
2021
using Moq;
2122
using Xunit;
@@ -642,5 +643,51 @@ private List<int> AllIndexesOf(string str, string value)
642643
}
643644

644645
#endregion
646+
647+
[Fact]
648+
public async Task WhenMetricsAsyncRaceConditionItemSameKeyExists_ValidateLock()
649+
{
650+
// Arrange
651+
var methodName = Guid.NewGuid().ToString();
652+
var consoleOut = new StringWriter();
653+
Console.SetOut(consoleOut);
654+
655+
var configurations = new Mock<IPowertoolsConfigurations>();
656+
657+
var metrics = new Metrics(configurations.Object,
658+
nameSpace: "dotnet-powertools-test",
659+
service: "testService");
660+
661+
var handler = new MetricsAspectHandler(metrics,
662+
false);
663+
664+
var eventArgs = new AspectEventArgs { Name = methodName };
665+
666+
// Act
667+
handler.OnEntry(eventArgs);
668+
669+
var tasks = new List<Task>();
670+
for (var i = 0; i < 100; i++)
671+
{
672+
tasks.Add(Task.Run(() =>
673+
{
674+
Metrics.AddMetric($"Metric Name", 0, MetricUnit.Count);
675+
}));
676+
}
677+
678+
await Task.WhenAll(tasks);
679+
680+
681+
handler.OnExit(eventArgs);
682+
683+
var metricsOutput = consoleOut.ToString();
684+
685+
// Assert
686+
Assert.Contains("{\"Namespace\":\"dotnet-powertools-test\",\"Metrics\":[{\"Name\":\"Metric Name\",\"Unit\":\"Count\"}],\"Dimensions\":[[\"Service\"]]",
687+
metricsOutput);
688+
689+
// Reset
690+
handler.ResetForTest();
691+
}
645692
}
646693
}

0 commit comments

Comments
 (0)