}
Activity? activity = null;
+ ActivityTagsCollection? samplerTags;
- ActivityDataRequest dataRequest = ActivityDataRequest.None;
- bool? useContext = default;
- ActivityCreationOptions<ActivityContext> optionsWithContext = default;
+ ActivitySamplingResult samplingResult = ActivitySamplingResult.None;
if (parentId != null)
{
var aco = new ActivityCreationOptions<string>(this, name, parentId, kind, tags, links);
- listeners.EnumWithFunc((ActivityListener listener, ref ActivityCreationOptions<string> data, ref ActivityDataRequest request, ref bool? canUseContext, ref ActivityCreationOptions<ActivityContext> dataWithContext) => {
- GetRequestedData<string>? getRequestedDataUsingParentId = listener.GetRequestedDataUsingParentId;
- if (getRequestedDataUsingParentId != null)
+ var acoContext = new ActivityCreationOptions<ActivityContext>(this, name, aco.GetContext(), kind, tags, links);
+
+ listeners.EnumWithFunc((ActivityListener listener, ref ActivityCreationOptions<string> data, ref ActivitySamplingResult result, ref ActivityCreationOptions<ActivityContext> dataWithContext) => {
+ SampleActivity<string>? sampleUsingParentId = listener.SampleUsingParentId;
+ if (sampleUsingParentId != null)
{
- ActivityDataRequest dr = getRequestedDataUsingParentId(ref data);
- if (dr > request)
+ ActivitySamplingResult sr = sampleUsingParentId(ref data);
+ if (sr > result)
{
- request = dr;
+ result = sr;
}
-
- // Stop the enumeration if we get the max value RecordingAndSampling.
- return request != ActivityDataRequest.AllDataAndRecorded;
}
else
{
- // In case we have a parent Id and the listener not providing the GetRequestedDataUsingParentId, we'll try to find out if the following conditions are true:
- // - The listener is providing the GetRequestedDataUsingContext callback
- // - Can convert the parent Id to a Context
- // Then we can call the listener GetRequestedDataUsingContext callback with the constructed context.
- GetRequestedData<ActivityContext>? getRequestedDataUsingContext = listener.GetRequestedDataUsingContext;
- if (getRequestedDataUsingContext != null)
+ // In case we have a parent Id and the listener not providing the SampleUsingParentId, we'll try to find out if the following conditions are true:
+ // - The listener is providing the Sample callback
+ // - Can convert the parent Id to a Context. ActivityCreationOptions.TraceId != default means parent id converted to a valid context.
+ // Then we can call the listener Sample callback with the constructed context.
+ SampleActivity<ActivityContext>? sample = listener.Sample;
+ if (sample != null && data.GetContext() != default) // data.GetContext() != default means parent Id parsed correctly to a context
{
- if (!canUseContext.HasValue)
+ ActivitySamplingResult sr = sample(ref dataWithContext);
+ if (sr > result)
{
- canUseContext = Activity.TryConvertIdToContext(parentId, traceState: null, out ActivityContext ctx);
- if (canUseContext.Value)
- {
- dataWithContext = new ActivityCreationOptions<ActivityContext>(data.Source, data.Name, ctx, data.Kind, data.Tags, data.Links);
- }
+ result = sr;
}
+ }
+ }
+ }, ref aco, ref samplingResult, ref acoContext);
- if (canUseContext.Value)
- {
- ActivityDataRequest dr = getRequestedDataUsingContext(ref dataWithContext);
- if (dr > request)
- {
- request = dr;
- }
- // Stop the enumeration if we get the max value RecordingAndSampling.
- return request != ActivityDataRequest.AllDataAndRecorded;
- }
+ if (context == default && aco.GetContext() != default)
+ {
+ context = aco.GetContext();
+ parentId = null;
+ }
+
+ samplerTags = aco.GetSamplingTags();
+ ActivityTagsCollection? atc = acoContext.GetSamplingTags();
+ if (atc != null)
+ {
+ if (samplerTags == null)
+ {
+ samplerTags = atc;
+ }
+ else
+ {
+ foreach (KeyValuePair<string, object> tag in atc)
+ {
+ samplerTags.Add(tag);
}
}
- return true;
- }, ref aco, ref dataRequest, ref useContext, ref optionsWithContext);
+ }
}
else
{
- ActivityContext initializedContext = context == default && Activity.Current != null ? Activity.Current.Context : context;
- optionsWithContext = new ActivityCreationOptions<ActivityContext>(this, name, initializedContext, kind, tags, links);
- listeners.EnumWithFunc((ActivityListener listener, ref ActivityCreationOptions<ActivityContext> data, ref ActivityDataRequest request, ref bool? canUseContext, ref ActivityCreationOptions<ActivityContext> dataWithContext) => {
- GetRequestedData<ActivityContext>? getRequestedDataUsingContext = listener.GetRequestedDataUsingContext;
- if (getRequestedDataUsingContext != null)
+ bool useCurrentActivityContext = context == default && Activity.Current != null;
+ var aco = new ActivityCreationOptions<ActivityContext>(this, name, useCurrentActivityContext ? Activity.Current!.Context : context, kind, tags, links);
+ listeners.EnumWithFunc((ActivityListener listener, ref ActivityCreationOptions<ActivityContext> data, ref ActivitySamplingResult result, ref ActivityCreationOptions<ActivityContext> unused) => {
+ SampleActivity<ActivityContext>? sample = listener.Sample;
+ if (sample != null)
{
- if (listener.AutoGenerateRootContextTraceId && !canUseContext.HasValue && data.Parent == default)
- {
- ActivityContext ctx = new ActivityContext(ActivityTraceId.CreateRandom(), default, default);
- dataWithContext = new ActivityCreationOptions<ActivityContext>(data.Source, data.Name, ctx, data.Kind, data.Tags, data.Links);
- canUseContext = true;
- }
- ActivityDataRequest dr = getRequestedDataUsingContext(ref data);
- if (dr > request)
+ ActivitySamplingResult dr = sample(ref data);
+ if (dr > result)
{
- request = dr;
+ result = dr;
}
-
- // Stop the enumeration if we get the max value RecordingAndSampling.
- return request != ActivityDataRequest.AllDataAndRecorded;
}
- return true;
- }, ref optionsWithContext, ref dataRequest, ref useContext, ref optionsWithContext);
- }
+ }, ref aco, ref samplingResult, ref aco);
- if (dataRequest != ActivityDataRequest.None)
- {
- if (useContext.HasValue && useContext.Value)
+ if (!useCurrentActivityContext)
{
- context = optionsWithContext.Parent;
- parentId = null;
+ // We use the context stored inside ActivityCreationOptions as it is possible the trace id get automatically generated during the sampling.
+ // We don't use the context stored inside ActivityCreationOptions only in case if we used Activity.Current context, the reason is we need to
+ // create the new child activity with Parent set to Activity.Current.
+ context = aco.GetContext();
}
- activity = Activity.CreateAndStart(this, name, kind, parentId, context, tags, links, startTime, dataRequest);
+ samplerTags = aco.GetSamplingTags();
+ }
+
+ if (samplingResult != ActivitySamplingResult.None)
+ {
+ activity = Activity.CreateAndStart(this, name, kind, parentId, context, tags, links, startTime, samplerTags, samplingResult);
listeners.EnumWithAction((listener, obj) => listener.ActivityStarted?.Invoke((Activity) obj), activity);
}
}
}
- internal delegate bool Function<T, TParent>(T item, ref ActivityCreationOptions<TParent> data, ref ActivityDataRequest dataRequest, ref bool? ctxInitialized, ref ActivityCreationOptions<ActivityContext> dataWithContext);
+ internal delegate void Function<T, TParent>(T item, ref ActivityCreationOptions<TParent> data, ref ActivitySamplingResult samplingResult, ref ActivityCreationOptions<ActivityContext> dataWithContext);
internal void AddListener(ActivityListener listener)
{
public int Count => _list.Count;
- public void EnumWithFunc<TParent>(ActivitySource.Function<T, TParent> func, ref ActivityCreationOptions<TParent> data, ref ActivityDataRequest dataRequest, ref bool? ctxInitialized, ref ActivityCreationOptions<ActivityContext> dataWithContext)
+ public void EnumWithFunc<TParent>(ActivitySource.Function<T, TParent> func, ref ActivityCreationOptions<TParent> data, ref ActivitySamplingResult samplingResult, ref ActivityCreationOptions<ActivityContext> dataWithContext)
{
uint version = _version;
int index = 0;
// Important to call the func outside the lock.
// This is the whole point we are having this wrapper class.
- if (!func(item, ref data, ref dataRequest, ref ctxInitialized, ref dataWithContext))
- {
- break;
- }
+ func(item, ref data, ref samplingResult, ref dataWithContext);
}
}
listener.ActivityStarted = activity => Assert.NotNull(activity);
listener.ActivityStopped = activity => Assert.NotNull(activity);
listener.ShouldListenTo = (activitySource) => object.ReferenceEquals(aSource, activitySource);
- listener.GetRequestedDataUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivityDataRequest.None;
- listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivityDataRequest.None;
+ listener.SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivitySamplingResult.None;
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.None;
ActivitySource.AddActivityListener(listener);
Assert.True(aSource.HasListeners());
listener.ActivityStarted = activity => counter++;
listener.ActivityStopped = activity => counter--;
listener.ShouldListenTo = (activitySource) => object.ReferenceEquals(aSource, activitySource);
- listener.GetRequestedDataUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivityDataRequest.AllDataAndRecorded;
- listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivityDataRequest.AllDataAndRecorded;
+ listener.SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivitySamplingResult.AllDataAndRecorded;
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.AllDataAndRecorded;
ActivitySource.AddActivityListener(listener);
listener.ActivityStarted = activity => Assert.NotNull(activity);
listener.ActivityStopped = activity => Assert.NotNull(activity);
listener.ShouldListenTo = (activitySource) => object.ReferenceEquals(aSource, activitySource);
- listener.GetRequestedDataUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivityDataRequest.AllData;
- listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivityDataRequest.AllData;
+ listener.SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivitySamplingResult.AllData;
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.AllData;
ActivitySource.AddActivityListener(listener);
listener.ActivityStarted = activity => activityStartCount++;
listener.ActivityStopped = activity => activityStopCount++;
listener.ShouldListenTo = (activitySource) => activitySource.Name == "" && activitySource.Version == "";
- listener.GetRequestedDataUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivityDataRequest.AllData;
- listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivityDataRequest.AllData;
+ listener.SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivitySamplingResult.AllData;
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.AllData;
ActivitySource.AddActivityListener(listener);
ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); },
ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); },
ShouldListenTo = (activitySource) => true,
- GetRequestedDataUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivityDataRequest.None,
- GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivityDataRequest.None
+ SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivitySamplingResult.None,
+ Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.None
};
ActivitySource.AddActivityListener(listeners[0]);
ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); },
ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); },
ShouldListenTo = (activitySource) => true,
- GetRequestedDataUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivityDataRequest.PropagationData,
- GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivityDataRequest.PropagationData
+ SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivitySamplingResult.PropagationData,
+ Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.PropagationData
};
ActivitySource.AddActivityListener(listeners[1]);
ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); },
ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); },
ShouldListenTo = (activitySource) => true,
- GetRequestedDataUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivityDataRequest.AllData,
- GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivityDataRequest.AllData
+ SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivitySamplingResult.AllData,
+ Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.AllData
};
ActivitySource.AddActivityListener(listeners[2]);
ActivityStarted = (activity) => { activityStartCount++; Assert.NotNull(activity); },
ActivityStopped = (activity) => { activityStopCount++; Assert.NotNull(activity); },
ShouldListenTo = (activitySource) => true,
- GetRequestedDataUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivityDataRequest.AllDataAndRecorded,
- GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivityDataRequest.AllDataAndRecorded
+ SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivitySamplingResult.AllDataAndRecorded,
+ Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.AllDataAndRecorded
};
ActivitySource.AddActivityListener(listeners[3]);
listener.ActivityStarted = activity => Assert.NotNull(activity);
listener.ActivityStopped = activity => Assert.NotNull(activity);
listener.ShouldListenTo = (activitySource) => true;
- listener.GetRequestedDataUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivityDataRequest.AllData;
- listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivityDataRequest.AllData;
+ listener.SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) => ActivitySamplingResult.AllData;
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.AllData;
ActivitySource.AddActivityListener(listener);
using ActivityListener listener = new ActivityListener();
listener.ShouldListenTo = (activitySource) => activitySource.Name == "ParentContext";
- listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
{
Activity c = Activity.Current;
if (c != null)
Assert.Equal(c.Context, activityOptions.Parent);
}
- return ActivityDataRequest.AllData;
+ return ActivitySamplingResult.AllData;
};
ActivitySource.AddActivityListener(listener);
-
using Activity a = aSource.StartActivity("a", ActivityKind.Server, new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), 0));
using Activity b = aSource.StartActivity("b");
Assert.Equal(a.Context, b.Parent.Context);
using ActivityListener listener3 = new ActivityListener(); // will have both context and parent Id callbacks
listener1.ShouldListenTo = listener2.ShouldListenTo = listener3.ShouldListenTo = (activitySource) => activitySource.Name == "ParentIdsTest";
- listener1.GetRequestedDataUsingContext = listener3.GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
+ listener1.Sample = listener3.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
{
callingByContext++;
Assert.Equal(new ActivityContext(ActivityTraceId.CreateFromString(w3cId.AsSpan(3, 32)), ActivitySpanId.CreateFromString(w3cId.AsSpan(36, 16)), ActivityTraceFlags.Recorded),
activityOptions.Parent);
- return ActivityDataRequest.AllData;
+ return ActivitySamplingResult.AllData;
};
- listener2.GetRequestedDataUsingParentId = listener3.GetRequestedDataUsingParentId = (ref ActivityCreationOptions<string> activityOptions) =>
+ listener2.SampleUsingParentId = listener3.SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) =>
{
callingByParentId++;
- return ActivityDataRequest.AllData;
+ return ActivitySamplingResult.AllData;
};
ActivitySource.AddActivityListener(listener1);
using ActivityListener listener = new ActivityListener();
listener.ShouldListenTo = (activitySource) => activitySource.Name == "RemoteContext";
- listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
{
isRemote = activityOptions.Parent.IsRemote;
- return ActivityDataRequest.AllData;
+ return ActivitySamplingResult.AllData;
};
ActivitySource.AddActivityListener(listener);
ActivityContext ctx = default;
- listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
+ bool forceGenerateTraceId = false;
+
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
{
- ctx = activityOptions.Parent;
- return ActivityDataRequest.AllData;
+ ctx = forceGenerateTraceId ? new ActivityContext(activityOptions.TraceId, default, default) : activityOptions.Parent;
+ return ActivitySamplingResult.AllData;
};
ActivitySource.AddActivityListener(listener);
Assert.Equal(default, ctx);
}
- listener.AutoGenerateRootContextTraceId = true;
+ forceGenerateTraceId = true;
Activity activity = aSource.StartActivity("a2", default, ctx);
ActivityContext ctx = default;
- listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
{
- ctx = activityOptions.Parent;
- return ActivityDataRequest.AllData;
+ ctx = new ActivityContext(activityOptions.TraceId, default, default);
+ return ActivitySamplingResult.AllData;
};
- listener.AutoGenerateRootContextTraceId = true;
ActivitySource.AddActivityListener(listener);
Activity activity = aSource.StartActivity("a2", default, null);
using ActivityListener listener = new ActivityListener();
listener.ShouldListenTo = (activitySource) => activitySource.Name == "EventNotificationOrder";
- listener.GetRequestedDataUsingContext = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivityDataRequest.AllData;
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.AllData;
listener.ActivityStopped = a => Assert.Equal(child, Activity.Current);
ActivitySource.AddActivityListener(listener);
}).Dispose();
}
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ public void TestAddingSamplerTags()
+ {
+ RemoteExecutor.Invoke(() => {
+
+ using ActivitySource aSource = new ActivitySource("SamplerTags1");
+ using ActivityListener listener = new ActivityListener();
+ listener.ShouldListenTo = (activitySource) => activitySource.Name == "SamplerTags1";
+
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
+ {
+ activityOptions.SamplingTags.Add("tag1", "value1");
+ activityOptions.SamplingTags.Add("tag2", "value2");
+ return ActivitySamplingResult.AllData;
+ };
+
+ ActivitySource.AddActivityListener(listener);
+
+ using Activity activity = aSource.StartActivity("a1");
+
+ Assert.NotNull(activity);
+ Assert.Equal(2, activity.TagObjects.Count());
+ Assert.Equal(new KeyValuePair<string, object>("tag1", "value1"), activity.TagObjects.ElementAt(0));
+ Assert.Equal(new KeyValuePair<string, object>("tag2", "value2"), activity.TagObjects.ElementAt(1));
+ }).Dispose();
+ }
+
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ public void TestAddingSamplerTagsUsingParentId()
+ {
+ RemoteExecutor.Invoke(() => {
+
+ using ActivitySource aSource = new ActivitySource("SamplerTags2");
+ using ActivityListener listener = new ActivityListener();
+ listener.ShouldListenTo = (activitySource) => activitySource.Name == "SamplerTags2";
+
+ listener.SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) =>
+ {
+ activityOptions.SamplingTags.Add("tag1", "value1");
+ activityOptions.SamplingTags.Add("tag2", "value2");
+ return ActivitySamplingResult.AllData;
+ };
+
+ ActivitySource.AddActivityListener(listener);
+
+ Activity activity = aSource.StartActivity("a1", ActivityKind.Client, "SomeParent");
+
+ Assert.NotNull(activity);
+ Assert.Equal(2, activity.TagObjects.Count());
+ Assert.Equal(new KeyValuePair<string, object>("tag1", "value1"), activity.TagObjects.ElementAt(0));
+ Assert.Equal(new KeyValuePair<string, object>("tag2", "value2"), activity.TagObjects.ElementAt(1));
+ }).Dispose();
+ }
+
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ public void TestNotAddedSamplerTags()
+ {
+ RemoteExecutor.Invoke(() => {
+
+ using ActivitySource aSource = new ActivitySource("SamplerTags3");
+ using ActivityListener listener = new ActivityListener();
+ listener.ShouldListenTo = (activitySource) => activitySource.Name == "SamplerTags3";
+
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
+ {
+ activityOptions.SamplingTags.Add("tag1", "value1");
+ Assert.False(true, "This callback shouldn't be called at all.");
+ return ActivitySamplingResult.AllData;
+ };
+
+ ActivitySource.AddActivityListener(listener);
+
+ // activity should be null as no listener asked for creation.
+ using Activity activity = aSource.StartActivity("a1", ActivityKind.Client, "NonW3CParentId");
+
+ Assert.Null(activity);
+ }).Dispose();
+ }
+
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ public void TestDefaultTraceIdWithHierarchicalParentId()
+ {
+ RemoteExecutor.Invoke(() => {
+
+ using ActivitySource aSource = new ActivitySource("SamplerTags4");
+ using ActivityListener listener = new ActivityListener();
+ listener.ShouldListenTo = (activitySource) => activitySource.Name == "SamplerTags4";
+
+ listener.SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) =>
+ {
+ Assert.Equal(default, activityOptions.TraceId);
+ return ActivitySamplingResult.AllData;
+ };
+
+ ActivitySource.AddActivityListener(listener);
+
+ Activity activity = aSource.StartActivity("a1", ActivityKind.Client, "HierarchicalParentId");
+
+ Assert.NotNull(activity);
+ // activity has no parent. expected default trace Id.
+ Assert.Equal(default, activity.TraceId);
+ }).Dispose();
+ }
+
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ public void TestAddingSamplerTagsFromMultipleListeners()
+ {
+ RemoteExecutor.Invoke(() => {
+ using ActivitySource aSource = new ActivitySource("SamplerTags5");
+ using ActivityListener listener1 = new ActivityListener();
+ using ActivityListener listener2 = new ActivityListener();
+ listener1.ShouldListenTo = (activitySource) => activitySource.Name == "SamplerTags5";
+ listener2.ShouldListenTo = (activitySource) => activitySource.Name == "SamplerTags5";
+
+ listener1.Sample = listener2.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
+ {
+ if (activityOptions.SamplingTags.Count == 0)
+ activityOptions.SamplingTags.Add("tag1", "value1");
+ else
+ activityOptions.SamplingTags.Add("tag2", "value2");
+
+ return ActivitySamplingResult.AllData;
+ };
+
+ ActivitySource.AddActivityListener(listener1);
+ ActivitySource.AddActivityListener(listener2);
+
+ using Activity activity = aSource.StartActivity("a1");
+
+ Assert.NotNull(activity);
+ Assert.Equal(2, activity.TagObjects.Count());
+ Assert.Equal(new KeyValuePair<string, object>("tag1", "value1"), activity.TagObjects.ElementAt(0));
+ Assert.Equal(new KeyValuePair<string, object>("tag2", "value2"), activity.TagObjects.ElementAt(1));
+ }).Dispose();
+ }
+
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ public void TestSamplerTagsWithMixedListenerModels()
+ {
+ RemoteExecutor.Invoke(() => {
+ const string w3cId = "00-99d43cb30a4cdb4fbeee3a19c29201b0-e82825765f051b47-01";
+
+ using ActivitySource aSource = new ActivitySource("SamplerTags6");
+ using ActivityListener listener1 = new ActivityListener();
+ using ActivityListener listener2 = new ActivityListener();
+ listener1.ShouldListenTo = (activitySource) => activitySource.Name == "SamplerTags6";
+ listener2.ShouldListenTo = (activitySource) => activitySource.Name == "SamplerTags6";
+
+ // listener1 provide SampleUsingParentId callback and doesn't provide Sample
+ listener1.SampleUsingParentId = (ref ActivityCreationOptions<string> activityOptions) =>
+ {
+ activityOptions.SamplingTags.Add("tag1", "value1");
+ return ActivitySamplingResult.AllData;
+ };
+
+ // listener2 provide Sample callback and doesn't provide SampleUsingParentId
+ // Sample should get called as we convert the w3c id to a context.
+ listener2.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
+ {
+ activityOptions.SamplingTags.Add("tag2", "value2");
+ return ActivitySamplingResult.AllData;
+ };
+
+ ActivitySource.AddActivityListener(listener1);
+ ActivitySource.AddActivityListener(listener2);
+
+ using Activity activity = aSource.StartActivity("a1", ActivityKind.Client, w3cId);
+
+ Assert.NotNull(activity);
+ Assert.Equal(2, activity.TagObjects.Count());
+ Assert.Equal(new KeyValuePair<string, object>("tag1", "value1"), activity.TagObjects.ElementAt(0));
+ Assert.Equal(new KeyValuePair<string, object>("tag2", "value2"), activity.TagObjects.ElementAt(1));
+ }).Dispose();
+ }
+
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ public void TestAddSamplerAndActivityCreationTags()
+ {
+ RemoteExecutor.Invoke(() => {
+ using ActivitySource aSource = new ActivitySource("SamplerTags7");
+ using ActivityListener listener = new ActivityListener();
+ listener.ShouldListenTo = (activitySource) => activitySource.Name == "SamplerTags7";
+
+ listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) =>
+ {
+ activityOptions.SamplingTags.Add("SamplerTag1", "SamplerValue1");
+ return ActivitySamplingResult.AllData;
+ };
+
+ ActivitySource.AddActivityListener(listener);
+
+ ActivityTagsCollection tags = new ActivityTagsCollection();
+ tags["tag1"] = "value1";
+ tags["tag2"] = "value2";
+
+ using Activity activity = aSource.StartActivity("a1", ActivityKind.Client, default(ActivityContext), tags);
+
+ Assert.NotNull(activity);
+ Assert.Equal(3, activity.TagObjects.Count());
+ Assert.Equal(new KeyValuePair<string, object>("tag1", "value1"), activity.TagObjects.ElementAt(0));
+ Assert.Equal(new KeyValuePair<string, object>("tag2", "value2"), activity.TagObjects.ElementAt(1));
+ Assert.Equal(new KeyValuePair<string, object>("SamplerTag1", "SamplerValue1"), activity.TagObjects.ElementAt(2));
+ }).Dispose();
+ }
+
public void Dispose() => Activity.Current = null;
}
}