Skip to content

Commit 528a647

Browse files
authored
Remove global state to try to fix flake (#7291)
## Summary of changes Remove usages of `Tracer.Instance` to try to stop flake ## Reason for change I've seen flake in these unit tests: e.g. ``` InjectTraceIntoData_WithJsonString_AddsTraceContext from Datadog.Trace.ClrProfiler.Managed.Tests.AutoInstrumentation.AWS.Kinesis.ContextPropagationTests (Datadog) The given key 'dd-pathway-ctx-base64' was not present in the dictionary. ``` My strong suspicion is that that flake is due to the fact that the tested classes are using `Tracer.Instance` state, which is global, and so state is leaking between tests. Also, the tracers weren't being disposed, so we were likely leaking threads. ## Implementation details - Inject a `Tracer` instance instead of grabbing the global one - Use `TracerHelper.Create()` and dispose the returned agent ## Test coverage Covered by existing tests ## Other details I suspect the actual flake was introduced by - #7244 <!-- ⚠️ Note: where possible, please obtain 2 approvals prior to merging. Unless CODEOWNERS specifies otherwise, for external teams it is typically best to have one review from a team member, and one review from apm-dotnet. Trivial changes do not require 2 reviews. -->
1 parent fca2ab4 commit 528a647

24 files changed

+147
-121
lines changed

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/EventBridge/ContextPropagation.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ internal static class ContextPropagation
2323
private const int MaxSizeBytes = 256 * 1024; // 256 KB
2424

2525
// Loops through all entries of the EventBridge event and tries to inject Datadog context into each.
26-
public static void InjectContext<TPutEventsRequest>(TPutEventsRequest request, PropagationContext context)
26+
public static void InjectContext<TPutEventsRequest>(Tracer tracer, TPutEventsRequest request, PropagationContext context)
2727
where TPutEventsRequest : IPutEventsRequest, IDuckType
2828
{
2929
var entries = request.Entries.Value;
@@ -37,14 +37,14 @@ public static void InjectContext<TPutEventsRequest>(TPutEventsRequest request, P
3737
var duckEntry = entry.DuckCast<IPutEventsRequestEntry>();
3838
if (duckEntry != null)
3939
{
40-
InjectHeadersIntoDetail(duckEntry, context);
40+
InjectHeadersIntoDetail(tracer, duckEntry, context);
4141
}
4242
}
4343
}
4444

4545
// Tries to add Datadog trace context under the `_datadog` key at the top level of the `detail` field.
4646
// `detail` is a string, so we have to manually modify it using a StringBuilder.
47-
private static void InjectHeadersIntoDetail(IPutEventsRequestEntry entry, PropagationContext context)
47+
private static void InjectHeadersIntoDetail(Tracer tracer, IPutEventsRequestEntry entry, PropagationContext context)
4848
{
4949
var detail = entry.Detail?.Trim() ?? "{}";
5050
if (!detail.EndsWith("}"))
@@ -61,7 +61,7 @@ private static void InjectHeadersIntoDetail(IPutEventsRequestEntry entry, Propag
6161
detailBuilder.Append(','); // Add comma if the original detail is not empty
6262
}
6363

64-
var traceContext = BuildContextJson(context, entry.EventBusName);
64+
var traceContext = BuildContextJson(tracer, context, entry.EventBusName);
6565
detailBuilder.Append($"\"{DatadogKey}\":{traceContext}").Append('}');
6666

6767
// Check new detail size
@@ -77,13 +77,13 @@ private static void InjectHeadersIntoDetail(IPutEventsRequestEntry entry, Propag
7777
}
7878

7979
// Builds a JSON string containing Datadog trace context
80-
private static string BuildContextJson(PropagationContext context, string? eventBusName)
80+
private static string BuildContextJson(Tracer tracer, PropagationContext context, string? eventBusName)
8181
{
8282
// Inject trace context
8383
var jsonBuilder = Util.StringBuilderCache.Acquire();
8484
jsonBuilder.Append('{');
8585

86-
Tracer.Instance.TracerManager.SpanContextPropagator.Inject(context, jsonBuilder, new StringBuilderCarrierSetter());
86+
tracer.TracerManager.SpanContextPropagator.Inject(context, jsonBuilder, new StringBuilderCarrierSetter());
8787

8888
// Inject start time and bus name
8989
var startTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/EventBridge/PutEventsAsyncIntegration.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ internal static CallTargetState OnMethodBegin<TTarget, TPutEventsRequest>(TTarge
5050
return CallTargetState.GetDefault();
5151
}
5252

53-
var scope = AwsEventBridgeCommon.CreateScope(Tracer.Instance, Operation, SpanKind, out var tags);
53+
var tracer = Tracer.Instance;
54+
var scope = AwsEventBridgeCommon.CreateScope(tracer, Operation, SpanKind, out var tags);
5455
if (tags is not null)
5556
{
5657
var busName = AwsEventBridgeCommon.GetBusName(request.Entries.Value);
@@ -63,7 +64,7 @@ internal static CallTargetState OnMethodBegin<TTarget, TPutEventsRequest>(TTarge
6364
}
6465

6566
var context = new PropagationContext(scope?.Span.Context, Baggage.Current);
66-
ContextPropagation.InjectContext(request, context);
67+
ContextPropagation.InjectContext(tracer, request, context);
6768

6869
return new CallTargetState(scope);
6970
}

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/EventBridge/PutEventsIntegration.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ internal static CallTargetState OnMethodBegin<TTarget, TPutEventsRequest>(TTarge
4747
return CallTargetState.GetDefault();
4848
}
4949

50-
var scope = AwsEventBridgeCommon.CreateScope(Tracer.Instance, Operation, SpanKind, out var tags);
50+
var tracer = Tracer.Instance;
51+
var scope = AwsEventBridgeCommon.CreateScope(tracer, Operation, SpanKind, out var tags);
5152
if (tags is not null)
5253
{
5354
var busName = AwsEventBridgeCommon.GetBusName(request.Entries.Value);
@@ -60,7 +61,7 @@ internal static CallTargetState OnMethodBegin<TTarget, TPutEventsRequest>(TTarge
6061
}
6162

6263
var context = new PropagationContext(scope?.Span.Context, Baggage.Current);
63-
ContextPropagation.InjectContext(request, context);
64+
ContextPropagation.InjectContext(tracer, request, context);
6465

6566
return new CallTargetState(scope);
6667
}

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Kinesis/ContextPropagation.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ internal static class ContextPropagation
2424
private const int MaxDsmHeaderSize = 34;
2525
private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(ContextPropagation));
2626

27-
public static void InjectTraceIntoRecords<TRecordsRequest>(TRecordsRequest request, Scope? scope, string? streamName)
27+
public static void InjectTraceIntoRecords<TRecordsRequest>(Tracer tracer, TRecordsRequest request, Scope? scope, string? streamName)
2828
where TRecordsRequest : IContainsRecords
2929
{
3030
// request.Records is not null and has at least one element
@@ -35,11 +35,11 @@ public static void InjectTraceIntoRecords<TRecordsRequest>(TRecordsRequest reque
3535

3636
if (request.Records[0].DuckCast<IContainsData>() is { } record)
3737
{
38-
InjectTraceIntoData(record, scope, streamName);
38+
InjectTraceIntoData(tracer, record, scope, streamName);
3939
}
4040
}
4141

42-
public static void InjectTraceIntoData<TRecordRequest>(TRecordRequest record, Scope? scope, string? streamName)
42+
public static void InjectTraceIntoData<TRecordRequest>(Tracer tracer, TRecordRequest record, Scope? scope, string? streamName)
4343
where TRecordRequest : IContainsData
4444
{
4545
if (scope is null)
@@ -57,7 +57,7 @@ public static void InjectTraceIntoData<TRecordRequest>(TRecordRequest record, Sc
5757
var propagatedContext = new Dictionary<string, object>();
5858
if (scope.Span.Context != null && !string.IsNullOrEmpty(streamName))
5959
{
60-
var dataStreamsManager = Tracer.Instance.TracerManager.DataStreamsManager;
60+
var dataStreamsManager = tracer.TracerManager.DataStreamsManager;
6161
if (dataStreamsManager != null && dataStreamsManager.IsEnabled)
6262
{
6363
var payloadSize = jsonData?.Count > 0 && record.Data != null ? record.Data.Length : 0;
@@ -89,7 +89,7 @@ public static void InjectTraceIntoData<TRecordRequest>(TRecordRequest record, Sc
8989

9090
try
9191
{
92-
Tracer.Instance.TracerManager.SpanContextPropagator.Inject(context, propagatedContext, default(DictionaryGetterAndSetter));
92+
tracer.TracerManager.SpanContextPropagator.Inject(context, propagatedContext, default(DictionaryGetterAndSetter));
9393
jsonData[KinesisKey] = propagatedContext;
9494

9595
var memoryStreamData = DictionaryToMemoryStream(jsonData);

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Kinesis/PutRecordAsyncIntegration.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,14 @@ internal static CallTargetState OnMethodBegin<TTarget, TPutRecordRequest>(TTarge
5050
return CallTargetState.GetDefault();
5151
}
5252

53-
var scope = AwsKinesisCommon.CreateScope(Tracer.Instance, Operation, SpanKinds.Producer, null, out var tags);
53+
var tracer = Tracer.Instance;
54+
var scope = AwsKinesisCommon.CreateScope(tracer, Operation, SpanKinds.Producer, null, out var tags);
5455
if (tags is not null)
5556
{
5657
tags.StreamName = request.StreamName;
5758
}
5859

59-
ContextPropagation.InjectTraceIntoData(request, scope, request.StreamName);
60+
ContextPropagation.InjectTraceIntoData(tracer, request, scope, request.StreamName);
6061

6162
return new CallTargetState(scope);
6263
}

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Kinesis/PutRecordAsyncV3_7Integration.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,15 @@ internal static CallTargetState OnMethodBegin<TTarget, TPutRecordRequest>(TTarge
5050
return CallTargetState.GetDefault();
5151
}
5252

53-
var scope = AwsKinesisCommon.CreateScope(Tracer.Instance, Operation, SpanKinds.Producer, null, out var tags);
53+
var tracer = Tracer.Instance;
54+
var scope = AwsKinesisCommon.CreateScope(tracer, Operation, SpanKinds.Producer, null, out var tags);
5455
var streamName = AwsKinesisCommon.GetStreamName(request);
5556
if (tags is not null)
5657
{
5758
tags.StreamName = streamName;
5859
}
5960

60-
ContextPropagation.InjectTraceIntoData(request, scope, streamName);
61+
ContextPropagation.InjectTraceIntoData(tracer, request, scope, streamName);
6162

6263
return new CallTargetState(scope);
6364
}

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Kinesis/PutRecordIntegration.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,14 @@ internal static CallTargetState OnMethodBegin<TTarget, TPutRecordRequest>(TTarge
4848
return CallTargetState.GetDefault();
4949
}
5050

51-
var scope = AwsKinesisCommon.CreateScope(Tracer.Instance, Operation, SpanKinds.Producer, null, out var tags);
51+
var tracer = Tracer.Instance;
52+
var scope = AwsKinesisCommon.CreateScope(tracer, Operation, SpanKinds.Producer, null, out var tags);
5253
if (tags is not null)
5354
{
5455
tags.StreamName = request.StreamName;
5556
}
5657

57-
ContextPropagation.InjectTraceIntoData(request, scope, request.StreamName);
58+
ContextPropagation.InjectTraceIntoData(tracer, request, scope, request.StreamName);
5859

5960
return new CallTargetState(scope);
6061
}

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Kinesis/PutRecordV3_7Integration.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,15 @@ internal static CallTargetState OnMethodBegin<TTarget, TPutRecordRequest>(TTarge
4848
return CallTargetState.GetDefault();
4949
}
5050

51-
var scope = AwsKinesisCommon.CreateScope(Tracer.Instance, Operation, SpanKinds.Producer, null, out var tags);
51+
var tracer = Tracer.Instance;
52+
var scope = AwsKinesisCommon.CreateScope(tracer, Operation, SpanKinds.Producer, null, out var tags);
5253
var streamName = AwsKinesisCommon.GetStreamName(request);
5354
if (tags is not null)
5455
{
5556
tags.StreamName = streamName;
5657
}
5758

58-
ContextPropagation.InjectTraceIntoData(request, scope, streamName);
59+
ContextPropagation.InjectTraceIntoData(tracer, request, scope, streamName);
5960

6061
return new CallTargetState(scope);
6162
}

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Kinesis/PutRecordsAsyncIntegration.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,14 @@ internal static CallTargetState OnMethodBegin<TTarget, TPutRecordsRequest>(TTarg
5050
return CallTargetState.GetDefault();
5151
}
5252

53-
var scope = AwsKinesisCommon.CreateScope(Tracer.Instance, Operation, SpanKinds.Producer, null, out var tags);
53+
var tracer = Tracer.Instance;
54+
var scope = AwsKinesisCommon.CreateScope(tracer, Operation, SpanKinds.Producer, null, out var tags);
5455
if (tags is not null)
5556
{
5657
tags.StreamName = request.StreamName;
5758
}
5859

59-
ContextPropagation.InjectTraceIntoRecords(request, scope, request.StreamName);
60+
ContextPropagation.InjectTraceIntoRecords(tracer, request, scope, request.StreamName);
6061

6162
return new CallTargetState(scope);
6263
}

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Kinesis/PutRecordsAsyncV3_7Integration.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,15 @@ internal static CallTargetState OnMethodBegin<TTarget, TPutRecordsRequest>(TTarg
5050
return CallTargetState.GetDefault();
5151
}
5252

53-
var scope = AwsKinesisCommon.CreateScope(Tracer.Instance, Operation, SpanKinds.Producer, null, out var tags);
53+
var tracer = Tracer.Instance;
54+
var scope = AwsKinesisCommon.CreateScope(tracer, Operation, SpanKinds.Producer, null, out var tags);
5455
var streamName = AwsKinesisCommon.GetStreamName(request);
5556
if (tags is not null)
5657
{
5758
tags.StreamName = streamName;
5859
}
5960

60-
ContextPropagation.InjectTraceIntoRecords(request, scope, streamName);
61+
ContextPropagation.InjectTraceIntoRecords(tracer, request, scope, streamName);
6162

6263
return new CallTargetState(scope);
6364
}

0 commit comments

Comments
 (0)