Skip to content

Commit 0719f68

Browse files
committed
Add debug-only guards for type
1 parent fe681a4 commit 0719f68

File tree

1 file changed

+24
-0
lines changed

1 file changed

+24
-0
lines changed

tracer/src/Datadog.Trace/Activity/Helpers/ActivityEnumerationHelper.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ internal static class ActivityEnumerationHelper
1616
{
1717
private static AllocationFreeEnumerator<IEnumerable<KeyValuePair<string, object?>>, KeyValuePair<string, object?>, OtelTagsEnumerationState>.AllocationFreeForEachDelegate? _tagObjectsEnumerator;
1818
private static AllocationFreeEnumerator<IEnumerable<KeyValuePair<string, string?>>, KeyValuePair<string, string?>, OtelTagsEnumerationState>.AllocationFreeForEachDelegate? _tagsEnumerator;
19+
#if DEBUG
20+
private static Type? _tagObjectsType;
21+
private static Type? _tagType;
22+
#endif
1923

2024
/// <summary>
2125
/// Returns an enumerator than can be used to iterate the provided <see cref="IActivity5.TagObjects"/>, without allocating.
@@ -26,27 +30,47 @@ internal static class ActivityEnumerationHelper
2630
public static AllocationFreeEnumerator<IEnumerable<KeyValuePair<string, object?>>, KeyValuePair<string, object?>, OtelTagsEnumerationState>.AllocationFreeForEachDelegate GetTagObjectsEnumerator<T>(T activity5)
2731
where T : IActivity5
2832
{
33+
#if DEBUG
34+
// Tag type used to call this method should never change
35+
if (Volatile.Read(ref _tagObjectsType) is { } expectedType)
36+
{
37+
System.Diagnostics.Debug.Assert(expectedType == activity5.TagObjects.GetType(), "Must always call this method with the same type of TagObjects");
38+
}
39+
#endif
2940
return Volatile.Read(ref _tagObjectsEnumerator) ?? BuildDelegate(activity5);
3041

3142
static AllocationFreeEnumerator<IEnumerable<KeyValuePair<string, object?>>, KeyValuePair<string, object?>, OtelTagsEnumerationState>.AllocationFreeForEachDelegate BuildDelegate(T activity5)
3243
{
3344
var forEach = AllocationFreeEnumerator<IEnumerable<KeyValuePair<string, object?>>, KeyValuePair<string, object?>, OtelTagsEnumerationState>
3445
.BuildAllocationFreeForEachDelegate(activity5.TagObjects.GetType());
3546

47+
#if DEBUG
48+
Volatile.Write(ref _tagObjectsType, activity5.TagObjects.GetType());
49+
#endif
3650
return Interlocked.CompareExchange(ref _tagObjectsEnumerator, forEach, null) ?? forEach;
3751
}
3852
}
3953

4054
public static AllocationFreeEnumerator<IEnumerable<KeyValuePair<string, string?>>, KeyValuePair<string, string?>, OtelTagsEnumerationState>.AllocationFreeForEachDelegate GetTagsEnumerator<T>(T activity)
4155
where T : IActivity
4256
{
57+
#if DEBUG
58+
// Tag type used to call this method should never change
59+
if (Volatile.Read(ref _tagType) is { } expectedType)
60+
{
61+
System.Diagnostics.Debug.Assert(expectedType == activity.Tags.GetType(), "Must always call this method with the same type of TagObjects");
62+
}
63+
#endif
4364
return Volatile.Read(ref _tagsEnumerator) ?? BuildDelegate(activity);
4465

4566
static AllocationFreeEnumerator<IEnumerable<KeyValuePair<string, string?>>, KeyValuePair<string, string?>, OtelTagsEnumerationState>.AllocationFreeForEachDelegate BuildDelegate(T activity)
4667
{
4768
var forEach = AllocationFreeEnumerator<IEnumerable<KeyValuePair<string, string?>>, KeyValuePair<string, string?>, OtelTagsEnumerationState>
4869
.BuildAllocationFreeForEachDelegate(activity.Tags.GetType());
4970

71+
#if DEBUG
72+
Volatile.Write(ref _tagType, activity.Tags.GetType());
73+
#endif
5074
return Interlocked.CompareExchange(ref _tagsEnumerator, forEach, null) ?? forEach;
5175
}
5276
}

0 commit comments

Comments
 (0)