internal void NotifyActivityStart(Activity activity) { Debug.Assert(activity != null); // _listeners can get assigned to null in Dispose. SynchronizedList <ActivityListener>?listeners = _listeners; if (listeners != null && listeners.Count > 0) { listeners.EnumWithAction(listener => listener.ActivityStarted?.Invoke(activity)); } }
/// <summary> /// Check if there is any listeners for this ActivitySource. /// This property can be helpful to tell if there is no listener, then no need to create Activity object /// and avoid creating the objects needed to create Activity (e.g. ActivityContext) /// Example of that is http scenario which can avoid reading the context data from the wire. /// </summary> public bool HasListeners() { SynchronizedList <ActivityListener>?listeners = _listeners; return(listeners != null && listeners.Count > 0); }
/// <summary> /// Dispose the ActivitySource object and remove the current instance from the global list. empty the listeners list too. /// </summary> public void Dispose() { _listeners = null; s_activeSources.Remove(this); }
private Activity?StartActivity(string name, ActivityKind kind, ActivityContext context, string?parentId, IEnumerable <KeyValuePair <string, string?> >?tags, IEnumerable <ActivityLink>?links, DateTimeOffset startTime) { // _listeners can get assigned to null in Dispose. SynchronizedList <ActivityListener>?listeners = _listeners; if (listeners == null || listeners.Count == 0) { return(null); } Activity?activity = null; ActivityDataRequest dateRequest = ActivityDataRequest.None; if (parentId != null) { listeners.EnumWithFunc(listener => { var getRequestedDataUsingParentId = listener.GetRequestedDataUsingParentId; if (getRequestedDataUsingParentId != null) { ActivityCreationOptions <string> aco = new ActivityCreationOptions <string>(this, name, parentId, kind, tags, links); ActivityDataRequest dr = getRequestedDataUsingParentId(ref aco); if (dr > dateRequest) { dateRequest = dr; } // Stop the enumeration if we get the max value RecordingAndSampling. return(dateRequest != ActivityDataRequest.AllDataAndRecorded); } return(true); }); } else { listeners.EnumWithFunc(listener => { var getRequestedDataUsingContext = listener.GetRequestedDataUsingContext; if (getRequestedDataUsingContext != null) { ActivityCreationOptions <ActivityContext> aco = new ActivityCreationOptions <ActivityContext>(this, name, context, kind, tags, links); ActivityDataRequest dr = getRequestedDataUsingContext(ref aco); if (dr > dateRequest) { dateRequest = dr; } // Stop the enumeration if we get the max value RecordingAndSampling. return(dateRequest != ActivityDataRequest.AllDataAndRecorded); } return(true); }); } if (dateRequest != ActivityDataRequest.None) { activity = Activity.CreateAndStart(this, name, kind, parentId, context, tags, links, startTime, dateRequest); listeners.EnumWithAction(listener => { var activityStarted = listener.ActivityStarted; if (activityStarted != null) { activityStarted(activity); } }); } return(activity); }
private Activity?CreateActivity(string name, ActivityKind kind, ActivityContext context, string?parentId, IEnumerable <KeyValuePair <string, object?> >?tags, IEnumerable <ActivityLink>?links, DateTimeOffset startTime, bool startIt = true, ActivityIdFormat idFormat = ActivityIdFormat.Unknown) { // _listeners can get assigned to null in Dispose. SynchronizedList <ActivityListener>?listeners = _listeners; if (listeners == null || listeners.Count == 0) { return(null); } Activity?activity = null; ActivityTagsCollection?samplerTags; string?traceState; ActivitySamplingResult samplingResult = ActivitySamplingResult.None; if (parentId != null) { ActivityCreationOptions <string> aco = default; ActivityCreationOptions <ActivityContext> acoContext = default; aco = new ActivityCreationOptions <string>(this, name, parentId, kind, tags, links, idFormat); if (aco.IdFormat == ActivityIdFormat.W3C) { // acoContext is used only in the Sample calls which called only when we have W3C Id format. acoContext = new ActivityCreationOptions <ActivityContext>(this, name, aco.GetContext(), kind, tags, links, ActivityIdFormat.W3C); } listeners.EnumWithFunc((ActivityListener listener, ref ActivityCreationOptions <string> data, ref ActivitySamplingResult result, ref ActivityCreationOptions <ActivityContext> dataWithContext) => { SampleActivity <string>?sampleUsingParentId = listener.SampleUsingParentId; if (sampleUsingParentId != null) { ActivitySamplingResult sr = sampleUsingParentId(ref data); dataWithContext.SetTraceState(data.TraceState); // Keep the trace state in sync between data and dataWithContext if (sr > result) { result = sr; } } else if (data.IdFormat == ActivityIdFormat.W3C) { // 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) { ActivitySamplingResult sr = sample(ref dataWithContext); data.SetTraceState(dataWithContext.TraceState); // Keep the trace state in sync between data and dataWithContext if (sr > result) { result = sr; } } } }, ref aco, ref samplingResult, ref acoContext); if (context == default) { if (aco.GetContext() != default) { context = aco.GetContext(); parentId = null; } else if (acoContext.GetContext() != default) { context = acoContext.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); } } } idFormat = aco.IdFormat; traceState = aco.TraceState; } else { bool useCurrentActivityContext = context == default && Activity.Current != null; var aco = new ActivityCreationOptions <ActivityContext>(this, name, useCurrentActivityContext ? Activity.Current !.Context : context, kind, tags, links, idFormat); listeners.EnumWithFunc((ActivityListener listener, ref ActivityCreationOptions <ActivityContext> data, ref ActivitySamplingResult result, ref ActivityCreationOptions <ActivityContext> unused) => { SampleActivity <ActivityContext>?sample = listener.Sample; if (sample != null) { ActivitySamplingResult dr = sample(ref data); if (dr > result) { result = dr; } } }, ref aco, ref samplingResult, ref aco); if (!useCurrentActivityContext) { // 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(); } samplerTags = aco.GetSamplingTags(); idFormat = aco.IdFormat; traceState = aco.TraceState; } if (samplingResult != ActivitySamplingResult.None) { activity = Activity.Create(this, name, kind, parentId, context, tags, links, startTime, samplerTags, samplingResult, startIt, idFormat, traceState); } return(activity); }
private Activity?StartActivity(string name, ActivityKind kind, ActivityContext context, string?parentId, IEnumerable <KeyValuePair <string, object?> >?tags, IEnumerable <ActivityLink>?links, DateTimeOffset startTime) { // _listeners can get assigned to null in Dispose. SynchronizedList <ActivityListener>?listeners = _listeners; if (listeners == null || listeners.Count == 0) { return(null); } Activity?activity = null; ActivityDataRequest dataRequest = ActivityDataRequest.None; bool?useContext = default; ActivityCreationOptions <ActivityContext> optionsWithContext = default; 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) { ActivityDataRequest dr = getRequestedDataUsingParentId(ref data); if (dr > request) { request = dr; } // 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) { if (!canUseContext.HasValue) { canUseContext = Activity.TryConvertIdToContext(parentId, out ActivityContext ctx); if (canUseContext.Value) { dataWithContext = new ActivityCreationOptions <ActivityContext>(data.Source, data.Name, ctx, data.Kind, data.Tags, data.Links); } } 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); } } } 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) { if (listener.AutoGenerateRootContextTraceId && !canUseContext.HasValue && data.Parent == default) { ActivityContext ctx = new ActivityContext(ActivityTraceId.CreateRandom(), default, default);
private Activity?StartActivity(string name, ActivityKind kind, ActivityContext context, string?parentId, IEnumerable <KeyValuePair <string, string?> >?tags, IEnumerable <ActivityLink>?links, DateTimeOffset startTime) { // _listeners can get assigned to null in Dispose. SynchronizedList <ActivityListener>?listeners = _listeners; if (listeners == null || listeners.Count == 0) { return(null); } Activity?activity = null; ActivityDataRequest dataRequest = ActivityDataRequest.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) => { GetRequestedData <string>?getRequestedDataUsingParentId = listener.GetRequestedDataUsingParentId; if (getRequestedDataUsingParentId != null) { ActivityDataRequest dr = getRequestedDataUsingParentId(ref data); if (dr > request) { request = dr; } // Stop the enumeration if we get the max value RecordingAndSampling. return(request != ActivityDataRequest.AllDataAndRecorded); } return(true); }, ref aco, ref dataRequest); } else { ActivityContext initializedContext = context == default && Activity.Current != null ? Activity.Current.Context : context; var aco = new ActivityCreationOptions <ActivityContext>(this, name, initializedContext, kind, tags, links); listeners.EnumWithFunc((ActivityListener listener, ref ActivityCreationOptions <ActivityContext> data, ref ActivityDataRequest request) => { GetRequestedData <ActivityContext>?getRequestedDataUsingContext = listener.GetRequestedDataUsingContext; if (getRequestedDataUsingContext != null) { ActivityDataRequest dr = getRequestedDataUsingContext(ref data); if (dr > request) { request = dr; } // Stop the enumeration if we get the max value RecordingAndSampling. return(request != ActivityDataRequest.AllDataAndRecorded); } return(true); }, ref aco, ref dataRequest); } if (dataRequest != ActivityDataRequest.None) { activity = Activity.CreateAndStart(this, name, kind, parentId, context, tags, links, startTime, dataRequest); listeners.EnumWithAction((listener, obj) => listener.ActivityStarted?.Invoke((Activity)obj), activity); } return(activity); }