diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs index b408cead906853..e7d36273408355 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs @@ -1233,7 +1233,9 @@ internal static Activity Create(ActivitySource source, string name, ActivityKind activity._parentSpanId = parentContext.SpanId.ToString(); } - activity.ActivityTraceFlags = parentContext.TraceFlags; + // Note: Don't inherit Recorded from parent as it is set below + // based on sampling decision + activity.ActivityTraceFlags = parentContext.TraceFlags & ~ActivityTraceFlags.Recorded; activity._parentTraceFlags = (byte)parentContext.TraceFlags; activity.HasRemoteParent = parentContext.IsRemote; } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs index 86227dc2e74275..5870822e5b03ad 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivitySourceTests.cs @@ -256,7 +256,7 @@ public void TestListeningToConstructedActivityEvents() } [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] - public void EnsureRecordingTest() + public void AllDataAndRecordedSamplingTest() { RemoteExecutor.Invoke(() => { Activity.ForceDefaultIdFormat = true; @@ -278,14 +278,76 @@ public void EnsureRecordingTest() ActivitySource.AddActivityListener(listener); - Activity a = aSource.StartActivity("RecordedActivity"); + // Note: Remote parent is set as NOT recorded + var parentContext = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, isRemote: true); + + Activity a = aSource.StartActivity("RecordedActivity", ActivityKind.Internal, parentContext); Assert.NotNull(a); + Assert.True(a.IsAllDataRequested); Assert.True(a.Recorded); Assert.True((a.Context.TraceFlags & ActivityTraceFlags.Recorded) != 0); }).Dispose(); } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void AllDataSamplingTest() + { + RemoteExecutor.Invoke(() => { + Activity.ForceDefaultIdFormat = true; + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + + ActivitySource aSource = new ActivitySource("EnsureRecordingTest"); + + ActivityListener listener = new ActivityListener + { + ShouldListenTo = (activitySource) => true, + Sample = (ref ActivityCreationOptions activityOptions) => ActivitySamplingResult.AllData + }; + + ActivitySource.AddActivityListener(listener); + + // Note: Remote parent is set as recorded + var parentContext = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded, isRemote: true); + + Activity a = aSource.StartActivity("RecordedActivity", ActivityKind.Internal, parentContext); + Assert.NotNull(a); + + Assert.True(a.IsAllDataRequested); + Assert.False(a.Recorded); + Assert.False((a.Context.TraceFlags & ActivityTraceFlags.Recorded) != 0); + }).Dispose(); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void PropagationDataSamplingTest() + { + RemoteExecutor.Invoke(() => { + Activity.ForceDefaultIdFormat = true; + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + + ActivitySource aSource = new ActivitySource("EnsureRecordingTest"); + + ActivityListener listener = new ActivityListener + { + ShouldListenTo = (activitySource) => true, + Sample = (ref ActivityCreationOptions activityOptions) => ActivitySamplingResult.PropagationData + }; + + ActivitySource.AddActivityListener(listener); + + // Note: Remote parent is set as recorded + var parentContext = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded, isRemote: true); + + Activity a = aSource.StartActivity("RecordedActivity", ActivityKind.Internal, parentContext); + Assert.NotNull(a); + + Assert.False(a.IsAllDataRequested); + Assert.False(a.Recorded); + Assert.False((a.Context.TraceFlags & ActivityTraceFlags.Recorded) != 0); + }).Dispose(); + } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void TestExpectedListenersReturnValues() { @@ -424,7 +486,10 @@ public void TestActivityCreationProperties() Assert.Equal(ctx.TraceId, activity.TraceId); Assert.Equal(ctx.SpanId, activity.ParentSpanId); - Assert.Equal(ctx.TraceFlags, activity.ActivityTraceFlags); + Assert.NotEqual(ctx.TraceFlags, activity.ActivityTraceFlags); + Assert.True(ctx.TraceFlags.HasFlag(ActivityTraceFlags.Recorded)); + Assert.False(activity.ActivityTraceFlags.HasFlag(ActivityTraceFlags.Recorded)); + Assert.False(activity.Recorded); Assert.Equal(ctx.TraceState, activity.TraceStateString); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat);