Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
43602c8
Initial plan for issue
Copilot May 21, 2025
7eb6299
Add thread safety to dictionary operations in Trace class
Copilot May 21, 2025
c8617fb
Update ITrace documentation to note thread safety
Copilot May 21, 2025
67a1c40
Replace locks with ConcurrentDictionary in Trace class
Copilot May 21, 2025
02999b2
Move thread safety comments from interface to implementation
Copilot May 21, 2025
84f78f7
Revert to Lazy<Dictionary> while maintaining thread safety
Copilot May 21, 2025
66efc2a
Use Lazy<ConcurrentDictionary> for thread safety without locks
Copilot May 21, 2025
bdc9edb
Fix AddDatum to maintain API contract by throwing ArgumentException f…
Copilot May 21, 2025
5a2e4c4
Improve thread safety test with more specific assertions
Copilot May 21, 2025
46f48ef
Revert to simpler test assertions as requested
Copilot May 21, 2025
5179a59
Merge branch 'master' into copilot/fix-5111
sourabh1007 May 23, 2025
bba23bf
Use OrderedConcurrentDictionary to maintain element order while prese…
Copilot May 27, 2025
4f002b9
Revert to ConcurrentDictionary to address ordering issues
Copilot May 27, 2025
32f10db
Merge branch 'master' into copilot/fix-5111
kirankumarkolli Jun 27, 2025
b1a0b69
Merge branch 'master' into copilot/fix-5111
kirankumarkolli Jul 6, 2025
584468c
Merge branch 'master' into copilot/fix-5111
kirankumarkolli Jul 11, 2025
2170a32
Merge branch 'master' into copilot/fix-5111
FabianMeiswinkel Aug 14, 2025
8924def
Update Trace.cs
FabianMeiswinkel Aug 18, 2025
d520f50
Update Trace.cs
FabianMeiswinkel Aug 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Microsoft.Azure.Cosmos/src/Tracing/ITrace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,20 +90,23 @@ ITrace StartChild(

/// <summary>
/// Adds a datum to the this trace instance.
/// This method is thread-safe.
Comment thread
FabianMeiswinkel marked this conversation as resolved.
Outdated
/// </summary>
/// <param name="key">The key to associate the datum.</param>
/// <param name="traceDatum">The datum itself.</param>
void AddDatum(string key, TraceDatum traceDatum);

/// <summary>
/// Adds a datum to the this trace instance.
/// This method is thread-safe.
/// </summary>
/// <param name="key">The key to associate the datum.</param>
/// <param name="value">The datum itself.</param>
void AddDatum(string key, object value);

/// <summary>
/// Updates the given datum in this trace instance if exists, otherwise Add
/// This method is thread-safe.
/// </summary>
/// <param name="key">The key to associate the datum.</param>
/// <param name="value">The datum itself.</param>
Expand Down
17 changes: 13 additions & 4 deletions Microsoft.Azure.Cosmos/src/Tracing/Trace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,27 @@ public static Trace GetRootTrace(

public void AddDatum(string key, TraceDatum traceDatum)
{
this.data.Value.Add(key, traceDatum);
this.Summary.UpdateRegionContacted(traceDatum);
lock (this.data)
Comment thread
FabianMeiswinkel marked this conversation as resolved.
Outdated
{
this.data.Value.Add(key, traceDatum);
this.Summary.UpdateRegionContacted(traceDatum);
}
}

public void AddDatum(string key, object value)
{
this.data.Value.Add(key, value);
lock (this.data)
{
this.data.Value.Add(key, value);
}
}

public void AddOrUpdateDatum(string key, object value)
{
this.data.Value[key] = value;
lock (this.data)
{
this.data.Value[key] = value;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Diagnostics;
using Microsoft.Azure.Cosmos.Json;
using Microsoft.Azure.Cosmos.Tracing;
Expand Down Expand Up @@ -134,5 +135,50 @@ public void ValidateStoreResultSerialization()

Assert.AreEqual(0, storeResultProperties.Count, $"Json is missing properties: {string.Join(';', storeResultProperties)}");
}
[TestMethod]
public void TestAddOrUpdateDatumThreadSafety()
{
Trace trace = Trace.GetRootTrace("ThreadSafetyTest");

// Create multiple threads to access the dictionary concurrently
const int numThreads = 10;
const int operationsPerThread = 100;

// Use a list to keep track of the tasks
List<Task> tasks = new List<Task>();

for (int i = 0; i < numThreads; i++)
{
int threadIndex = i;
tasks.Add(Task.Run(() =>
{
for (int j = 0; j < operationsPerThread; j++)
{
string key = $"key_{threadIndex}_{j}";
object value = j;

// Perform operations that would previously cause thread safety issues
trace.AddOrUpdateDatum(key, value);

// Also test AddDatum
try
{
trace.AddDatum($"add_{threadIndex}_{j}", value);
}
catch (ArgumentException)
{
// Ignore key already exists exceptions which may occur
// when threads try to add the same key
}
}
}));
}

// Wait for all tasks to complete
Task.WaitAll(tasks.ToArray());

// Verify the data dictionary has entries
Assert.IsTrue(trace.Data.Count > 0);
Comment thread
FabianMeiswinkel marked this conversation as resolved.
}
}
}
Loading