Skip to content

Commit b0bd80e

Browse files
authored
feat(tracing): thread safety and async context preservation in Powertools Tracing (#1082)
Signed-off-by: Henrique Graca <[email protected]>
1 parent 0c6cf50 commit b0bd80e

File tree

6 files changed

+1264
-12
lines changed

6 files changed

+1264
-12
lines changed

libraries/src/AWS.Lambda.Powertools.Tracing/Internal/TracingAspect.cs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using System.Runtime.ExceptionServices;
44
using System.Text;
5+
using System.Threading;
56
using System.Threading.Tasks;
67
using AspectInjector.Broker;
78
using AWS.Lambda.Powertools.Common;
@@ -28,14 +29,15 @@ public class TracingAspect
2829
private readonly IXRayRecorder _xRayRecorder;
2930

3031
/// <summary>
31-
/// If true, capture annotations
32+
/// Thread-safe flag for capturing annotations. Uses int for Interlocked operations.
33+
/// 1 = should capture, 0 = already captured
3234
/// </summary>
33-
private static bool _captureAnnotations = true;
35+
private static int _captureAnnotations = 1;
3436

3537
/// <summary>
36-
/// If true, annotations have been captured
38+
/// If true, annotations have been captured by this invocation's execution context
3739
/// </summary>
38-
private bool _isAnnotationsCaptured;
40+
private static readonly AsyncLocal<bool> _isAnnotationsCaptured = new();
3941

4042
/// <summary>
4143
/// Aspect constructor
@@ -117,8 +119,12 @@ public object Around(
117119
}
118120
finally
119121
{
120-
if (_isAnnotationsCaptured)
121-
_captureAnnotations = true;
122+
// Reset the capture flag if this execution context captured annotations
123+
if (_isAnnotationsCaptured.Value)
124+
{
125+
Interlocked.Exchange(ref _captureAnnotations, 1);
126+
_isAnnotationsCaptured.Value = false;
127+
}
122128
}
123129
}
124130

@@ -127,12 +133,12 @@ private void BeginSegment(string segmentName, string @namespace)
127133
_xRayRecorder.BeginSubsegment(segmentName);
128134
_xRayRecorder.SetNamespace(@namespace);
129135

130-
if (_captureAnnotations)
136+
// Use Interlocked.CompareExchange for thread-safe check-and-set
137+
// Only one thread will successfully change from 1 to 0
138+
if (Interlocked.CompareExchange(ref _captureAnnotations, 0, 1) == 1)
131139
{
132140
_xRayRecorder.AddAnnotation("ColdStart", LambdaLifecycleTracker.IsColdStart);
133-
134-
_captureAnnotations = false;
135-
_isAnnotationsCaptured = true;
141+
_isAnnotationsCaptured.Value = true;
136142

137143
if (_powertoolsConfigurations.IsServiceDefined)
138144
_xRayRecorder.AddAnnotation("Service", _powertoolsConfigurations.Service);
@@ -231,6 +237,7 @@ private bool CaptureError(TracingCaptureMode captureMode)
231237
internal static void ResetForTest()
232238
{
233239
LambdaLifecycleTracker.Reset();
234-
_captureAnnotations = true;
240+
Interlocked.Exchange(ref _captureAnnotations, 1);
241+
_isAnnotationsCaptured.Value = false;
235242
}
236243
}

libraries/src/Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<PackageVersion Include="AWSSDK.SecretsManager" Version="4.0.1.2" />
2222
<PackageVersion Include="AWSSDK.SimpleSystemsManagement" Version="4.0.3.2" />
2323
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
24-
<PackageVersion Include="AWSSDK.XRay" Version="4.0.2.1" />
24+
<PackageVersion Include="AWSSDK.XRay" Version="4.0.3.7" />
2525
<PackageVersion Include="AWSXRayRecorder.Core" Version="2.15.0" />
2626
<PackageVersion Include="Amazon.Lambda.DynamoDBEvents" Version="3.1.1" />
2727
<PackageVersion Include="Amazon.Lambda.KinesisEvents" Version="3.0.0" />

libraries/tests/AWS.Lambda.Powertools.ConcurrencyTests/AWS.Lambda.Powertools.ConcurrencyTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
<ItemGroup>
2727
<ProjectReference Include="..\..\src\AWS.Lambda.Powertools.Logging\AWS.Lambda.Powertools.Logging.csproj" />
2828
<ProjectReference Include="..\..\src\AWS.Lambda.Powertools.Metrics\AWS.Lambda.Powertools.Metrics.csproj" />
29+
<ProjectReference Include="..\..\src\AWS.Lambda.Powertools.Tracing\AWS.Lambda.Powertools.Tracing.csproj" />
2930
</ItemGroup>
3031

3132
</Project>

0 commit comments

Comments
 (0)