Skip to content

Commit 7eb6299

Browse files
Copilotsourabh1007
andcommitted
Add thread safety to dictionary operations in Trace class
Co-authored-by: sourabh1007 <6362382+sourabh1007@users.noreply.github.com>
1 parent 43602c8 commit 7eb6299

2 files changed

Lines changed: 59 additions & 4 deletions

File tree

Microsoft.Azure.Cosmos/src/Tracing/Trace.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,18 +124,27 @@ public static Trace GetRootTrace(
124124

125125
public void AddDatum(string key, TraceDatum traceDatum)
126126
{
127-
this.data.Value.Add(key, traceDatum);
128-
this.Summary.UpdateRegionContacted(traceDatum);
127+
lock (this.data)
128+
{
129+
this.data.Value.Add(key, traceDatum);
130+
this.Summary.UpdateRegionContacted(traceDatum);
131+
}
129132
}
130133

131134
public void AddDatum(string key, object value)
132135
{
133-
this.data.Value.Add(key, value);
136+
lock (this.data)
137+
{
138+
this.data.Value.Add(key, value);
139+
}
134140
}
135141

136142
public void AddOrUpdateDatum(string key, object value)
137143
{
138-
this.data.Value[key] = value;
144+
lock (this.data)
145+
{
146+
this.data.Value[key] = value;
147+
}
139148
}
140149
}
141150
}

Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Generic;
55
using System.Linq;
66
using System.Reflection;
7+
using System.Threading.Tasks;
78
using Microsoft.Azure.Cosmos.Diagnostics;
89
using Microsoft.Azure.Cosmos.Json;
910
using Microsoft.Azure.Cosmos.Tracing;
@@ -134,5 +135,50 @@ public void ValidateStoreResultSerialization()
134135

135136
Assert.AreEqual(0, storeResultProperties.Count, $"Json is missing properties: {string.Join(';', storeResultProperties)}");
136137
}
138+
[TestMethod]
139+
public void TestAddOrUpdateDatumThreadSafety()
140+
{
141+
Trace trace = Trace.GetRootTrace("ThreadSafetyTest");
142+
143+
// Create multiple threads to access the dictionary concurrently
144+
const int numThreads = 10;
145+
const int operationsPerThread = 100;
146+
147+
// Use a list to keep track of the tasks
148+
List<Task> tasks = new List<Task>();
149+
150+
for (int i = 0; i < numThreads; i++)
151+
{
152+
int threadIndex = i;
153+
tasks.Add(Task.Run(() =>
154+
{
155+
for (int j = 0; j < operationsPerThread; j++)
156+
{
157+
string key = $"key_{threadIndex}_{j}";
158+
object value = j;
159+
160+
// Perform operations that would previously cause thread safety issues
161+
trace.AddOrUpdateDatum(key, value);
162+
163+
// Also test AddDatum
164+
try
165+
{
166+
trace.AddDatum($"add_{threadIndex}_{j}", value);
167+
}
168+
catch (ArgumentException)
169+
{
170+
// Ignore key already exists exceptions which may occur
171+
// when threads try to add the same key
172+
}
173+
}
174+
}));
175+
}
176+
177+
// Wait for all tasks to complete
178+
Task.WaitAll(tasks.ToArray());
179+
180+
// Verify the data dictionary has entries
181+
Assert.IsTrue(trace.Data.Count > 0);
182+
}
137183
}
138184
}

0 commit comments

Comments
 (0)