<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="7.0.0-preview.7.22375.6" />

Activity

public class Activity : IDisposable
Represents an operation with context to be used for logging.
using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Text; using System.Threading; namespace System.Diagnostics { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public class Activity : IDisposable { [System.Runtime.CompilerServices.Nullable(0)] public struct Enumerator<[System.Runtime.CompilerServices.Nullable(2)] T> { private static readonly DiagNode<T> s_Empty = new DiagNode<T>(default(T)); private DiagNode<T> _nextNode; private DiagNode<T> _currentNode; public ref T Current { [System.Runtime.CompilerServices.IsReadOnly] get { return ref _currentNode.Value; } } internal Enumerator(DiagNode<T> head) { _nextNode = head; _currentNode = s_Empty; } [System.Runtime.CompilerServices.IsReadOnly] [EditorBrowsable(EditorBrowsableState.Never)] [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public Enumerator<T> GetEnumerator() { return this; } public bool MoveNext() { if (_nextNode == null) { _currentNode = s_Empty; return false; } _currentNode = _nextNode; _nextNode = _nextNode.Next; return true; } } private sealed class BaggageLinkedList : IEnumerable<KeyValuePair<string, string>>, IEnumerable { private DiagNode<KeyValuePair<string, string>> _first; public DiagNode<KeyValuePair<string, string>> First => _first; public BaggageLinkedList(KeyValuePair<string, string> firstValue, bool set = false) { _first = ((set && firstValue.Value == null) ? null : new DiagNode<KeyValuePair<string, string>>(firstValue)); } public void Add(KeyValuePair<string, string> value) { DiagNode<KeyValuePair<string, string>> diagNode = new DiagNode<KeyValuePair<string, string>>(value); lock (this) { diagNode.Next = _first; _first = diagNode; } } public void Set(KeyValuePair<string, string> value) { if (value.Value == null) Remove(value.Key); else { lock (this) { for (DiagNode<KeyValuePair<string, string>> diagNode = _first; diagNode != null; diagNode = diagNode.Next) { if (diagNode.Value.Key == value.Key) { diagNode.Value = value; return; } } DiagNode<KeyValuePair<string, string>> diagNode2 = new DiagNode<KeyValuePair<string, string>>(value); diagNode2.Next = _first; _first = diagNode2; } } } public void Remove(string key) { lock (this) { if (_first != null) { if (_first.Value.Key == key) _first = _first.Next; else { DiagNode<KeyValuePair<string, string>> diagNode = _first; while (true) { if (diagNode.Next == null) return; if (diagNode.Next.Value.Key == key) break; diagNode = diagNode.Next; } diagNode.Next = diagNode.Next.Next; } } } } public DiagEnumerator<KeyValuePair<string, string>> GetEnumerator() { return new DiagEnumerator<KeyValuePair<string, string>>(_first); } IEnumerator<KeyValuePair<string, string>> IEnumerable<KeyValuePair<string, string>>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal sealed class TagsLinkedList : IEnumerable<KeyValuePair<string, object>>, IEnumerable { private DiagNode<KeyValuePair<string, object>> _first; private DiagNode<KeyValuePair<string, object>> _last; private StringBuilder _stringBuilder; public DiagNode<KeyValuePair<string, object>> First => _first; public TagsLinkedList(KeyValuePair<string, object> firstValue, bool set = false) { _last = (_first = ((set && firstValue.Value == null) ? null : new DiagNode<KeyValuePair<string, object>>(firstValue))); } public TagsLinkedList(IEnumerator<KeyValuePair<string, object>> e) { _last = (_first = new DiagNode<KeyValuePair<string, object>>(e.Current)); while (e.MoveNext()) { _last.Next = new DiagNode<KeyValuePair<string, object>>(e.Current); _last = _last.Next; } } public TagsLinkedList(IEnumerable<KeyValuePair<string, object>> list) { Add(list); } public void Add(IEnumerable<KeyValuePair<string, object>> list) { IEnumerator<KeyValuePair<string, object>> enumerator = list.GetEnumerator(); if (enumerator.MoveNext()) { if (_first == null) _last = (_first = new DiagNode<KeyValuePair<string, object>>(enumerator.Current)); else { _last.Next = new DiagNode<KeyValuePair<string, object>>(enumerator.Current); _last = _last.Next; } while (enumerator.MoveNext()) { _last.Next = new DiagNode<KeyValuePair<string, object>>(enumerator.Current); _last = _last.Next; } } } public void Add(KeyValuePair<string, object> value) { DiagNode<KeyValuePair<string, object>> diagNode = new DiagNode<KeyValuePair<string, object>>(value); lock (this) { if (_first == null) _first = (_last = diagNode); else { _last.Next = diagNode; _last = diagNode; } } } public object Get(string key) { for (DiagNode<KeyValuePair<string, object>> diagNode = _first; diagNode != null; diagNode = diagNode.Next) { if (diagNode.Value.Key == key) return diagNode.Value.Value; } return null; } public void Remove(string key) { lock (this) { if (_first != null) { if (_first.Value.Key == key) { _first = _first.Next; if (_first == null) _last = null; } else { DiagNode<KeyValuePair<string, object>> diagNode = _first; while (true) { if (diagNode.Next == null) return; if (diagNode.Next.Value.Key == key) break; diagNode = diagNode.Next; } if (_last == diagNode.Next) _last = diagNode; diagNode.Next = diagNode.Next.Next; } } } } public void Set(KeyValuePair<string, object> value) { if (value.Value == null) Remove(value.Key); else { lock (this) { for (DiagNode<KeyValuePair<string, object>> diagNode = _first; diagNode != null; diagNode = diagNode.Next) { if (diagNode.Value.Key == value.Key) { diagNode.Value = value; return; } } DiagNode<KeyValuePair<string, object>> diagNode2 = new DiagNode<KeyValuePair<string, object>>(value); if (_first == null) _first = (_last = diagNode2); else { _last.Next = diagNode2; _last = diagNode2; } } } } public DiagEnumerator<KeyValuePair<string, object>> GetEnumerator() { return new DiagEnumerator<KeyValuePair<string, object>>(_first); } IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IEnumerable<KeyValuePair<string, string>> EnumerateStringValues() { for (DiagNode<KeyValuePair<string, object>> current = _first; current != null; current = current.Next) { if (current.Value.Value is string || current.Value.Value == null) yield return new KeyValuePair<string, string>(current.Value.Key, (string)current.Value.Value); } } public override string ToString() { lock (this) { if (_first != null) { if (_stringBuilder == null) _stringBuilder = new StringBuilder(); _stringBuilder.Append(_first.Value.Key); _stringBuilder.Append(':'); _stringBuilder.Append(_first.Value.Value); for (DiagNode<KeyValuePair<string, object>> next = _first.Next; next != null; next = next.Next) { _stringBuilder.Append(", "); _stringBuilder.Append(next.Value.Key); _stringBuilder.Append(':'); _stringBuilder.Append(next.Value.Value); } string result = _stringBuilder.ToString(); _stringBuilder.Clear(); return result; } return string.Empty; } } } [Flags] private enum State : byte { None = 0, FormatUnknown = 0, FormatHierarchical = 1, FormatW3C = 2, FormatFlags = 3, IsStopped = 128 } private static readonly IEnumerable<KeyValuePair<string, string>> s_emptyBaggageTags = new KeyValuePair<string, string>[0]; private static readonly IEnumerable<KeyValuePair<string, object>> s_emptyTagObjects = new KeyValuePair<string, object>[0]; private static readonly IEnumerable<ActivityLink> s_emptyLinks = new ActivityLink[0]; private static readonly IEnumerable<ActivityEvent> s_emptyEvents = new ActivityEvent[0]; private static readonly ActivitySource s_defaultSource = new ActivitySource(string.Empty, ""); private const byte ActivityTraceFlagsIsSet = 128; private const int RequestIdMaxLength = 1024; private static readonly string s_uniqSuffix = "-" + GetRandomNumber().ToString("x") + "."; private static long s_currentRootId = (uint)GetRandomNumber(); private static ActivityIdFormat s_defaultIdFormat; private string _traceState; private State _state; private int _currentChildId; private string _id; private string _rootId; private string _parentId; private string _parentSpanId; private string _traceId; private string _spanId; private byte _w3CIdFlags; private byte _parentTraceFlags; private TagsLinkedList _tags; private BaggageLinkedList _baggage; private DiagLinkedList<ActivityLink> _links; private DiagLinkedList<ActivityEvent> _events; private Dictionary<string, object> _customProperties; private string _displayName; private ActivityStatusCode _statusCode; private string _statusDescription; private Activity _previousActiveActivity; private static readonly AsyncLocal<Activity> s_current = new AsyncLocal<Activity>(); public static bool ForceDefaultIdFormat { get; set; } public ActivityStatusCode Status => _statusCode; [System.Runtime.CompilerServices.Nullable(2)] public string StatusDescription { [System.Runtime.CompilerServices.NullableContext(2)] get { return _statusDescription; } } public bool HasRemoteParent { get; set; } public ActivityKind Kind { get; set; } public string OperationName { get; } public string DisplayName { get { return _displayName ?? OperationName; } set { if (value == null) throw new ArgumentNullException("value"); _displayName = value; } } public ActivitySource Source { get; set; } [System.Runtime.CompilerServices.Nullable(2)] public Activity Parent { [System.Runtime.CompilerServices.NullableContext(2)] get; private set; } public TimeSpan Duration { get; set; } public DateTime StartTimeUtc { get; set; } [System.Runtime.CompilerServices.Nullable(2)] public unsafe string Id { [System.Runtime.CompilerServices.NullableContext(2)] get { if (_id == null && _spanId != null) { Span<char> span = new Span<char>(stackalloc byte[4], 2); Span<char> buffer = span; System.HexConverter.ToCharsBuffer((byte)(-129 & _w3CIdFlags), buffer, 0, System.HexConverter.Casing.Lower); string value = "00-" + _traceId + "-" + _spanId + "-" + buffer.ToString(); Interlocked.CompareExchange(ref _id, value, null); } return _id; } } [System.Runtime.CompilerServices.Nullable(2)] public unsafe string ParentId { [System.Runtime.CompilerServices.NullableContext(2)] get { if (_parentId == null) { if (_parentSpanId != null) { Span<char> span = new Span<char>(stackalloc byte[4], 2); Span<char> buffer = span; System.HexConverter.ToCharsBuffer((byte)(-129 & _parentTraceFlags), buffer, 0, System.HexConverter.Casing.Lower); string value = "00-" + _traceId + "-" + _parentSpanId + "-" + buffer.ToString(); Interlocked.CompareExchange(ref _parentId, value, null); } else if (Parent != null) { Interlocked.CompareExchange(ref _parentId, Parent.Id, null); } } return _parentId; } } [System.Runtime.CompilerServices.Nullable(2)] public string RootId { [System.Runtime.CompilerServices.NullableContext(2)] get { if (_rootId == null) { string text = null; if (Id != null) text = GetRootId(Id); else if (ParentId != null) { text = GetRootId(ParentId); } if (text != null) Interlocked.CompareExchange(ref _rootId, text, null); } return _rootId; } } [System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0, 1, 2 })] public IEnumerable<KeyValuePair<string, string>> Tags { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0, 1, 2 })] get { return _tags?.EnumerateStringValues() ?? s_emptyBaggageTags; } } [System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0, 1, 2 })] public IEnumerable<KeyValuePair<string, object>> TagObjects { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0, 1, 2 })] get { IEnumerable<KeyValuePair<string, object>> tags = _tags; return tags ?? s_emptyTagObjects; } } public IEnumerable<ActivityEvent> Events { get { IEnumerable<ActivityEvent> events = _events; return events ?? s_emptyEvents; } } public IEnumerable<ActivityLink> Links { get { IEnumerable<ActivityLink> links = _links; return links ?? s_emptyLinks; } } [System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0, 1, 2 })] public IEnumerable<KeyValuePair<string, string>> Baggage { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0, 1, 2 })] get { for (Activity activity = this; activity != null; activity = activity.Parent) { if (activity._baggage != null) return <get_Baggage>g__Iterate|87_0(activity); } return s_emptyBaggageTags; } } public ActivityContext Context => new ActivityContext(TraceId, SpanId, ActivityTraceFlags, TraceStateString, false); [System.Runtime.CompilerServices.Nullable(2)] public string TraceStateString { [System.Runtime.CompilerServices.NullableContext(2)] get { for (Activity activity = this; activity != null; activity = activity.Parent) { string traceState = activity._traceState; if (traceState != null) return traceState; } return null; } [System.Runtime.CompilerServices.NullableContext(2)] set { _traceState = value; } } public ActivitySpanId SpanId { get { if (_spanId == null && _id != null && IdFormat == ActivityIdFormat.W3C) { string value = ActivitySpanId.CreateFromString(_id.AsSpan(36, 16)).ToHexString(); Interlocked.CompareExchange(ref _spanId, value, null); } return new ActivitySpanId(_spanId); } } public ActivityTraceId TraceId { get { if (_traceId == null) TrySetTraceIdFromParent(); return new ActivityTraceId(_traceId); } } public bool Recorded => (ActivityTraceFlags & ActivityTraceFlags.Recorded) != ActivityTraceFlags.None; public bool IsAllDataRequested { get; set; } public ActivityTraceFlags ActivityTraceFlags { get { if (!W3CIdFlagsSet) TrySetTraceFlagsFromParent(); return (ActivityTraceFlags)(-129 & _w3CIdFlags); } set { _w3CIdFlags = (byte)(128 | (byte)value); } } public ActivitySpanId ParentSpanId { get { if (_parentSpanId == null) { string text = null; ActivitySpanId activitySpanId; if (_parentId != null && IsW3CId(_parentId)) try { activitySpanId = ActivitySpanId.CreateFromString(_parentId.AsSpan(36, 16)); text = activitySpanId.ToHexString(); } catch { } else if (Parent != null && Parent.IdFormat == ActivityIdFormat.W3C) { activitySpanId = Parent.SpanId; text = activitySpanId.ToHexString(); } if (text != null) Interlocked.CompareExchange(ref _parentSpanId, text, null); } return new ActivitySpanId(_parentSpanId); } } [System.Runtime.CompilerServices.Nullable(2)] public static Func<ActivityTraceId> TraceIdGenerator { [System.Runtime.CompilerServices.NullableContext(2)] get; [System.Runtime.CompilerServices.NullableContext(2)] set; } public static ActivityIdFormat DefaultIdFormat { get { if (s_defaultIdFormat == ActivityIdFormat.Unknown) s_defaultIdFormat = ActivityIdFormat.Hierarchical; return s_defaultIdFormat; } set { if (ActivityIdFormat.Hierarchical > value || value > ActivityIdFormat.W3C) throw new ArgumentException(System.SR.ActivityIdFormatInvalid); s_defaultIdFormat = value; } } private bool W3CIdFlagsSet => (_w3CIdFlags & 128) != 0; public bool IsStopped { get { return (_state & State.IsStopped) != State.None; } private set { if (value) _state |= State.IsStopped; else _state &= ~State.IsStopped; } } public ActivityIdFormat IdFormat { get { return (ActivityIdFormat)(_state & State.FormatFlags); } private set { _state = (State)((int)(_state & ~(State.FormatHierarchical | State.FormatW3C)) | (int)(byte)((byte)value & 3)); } } [System.Runtime.CompilerServices.Nullable(2)] public static Activity Current { [System.Runtime.CompilerServices.NullableContext(2)] get { return s_current.Value; } [System.Runtime.CompilerServices.NullableContext(2)] set { if (ValidateSetCurrent(value)) SetCurrent(value); } } [System.Runtime.CompilerServices.Nullable(2)] [method: System.Runtime.CompilerServices.NullableContext(2)] public static event EventHandler<ActivityChangedEventArgs> CurrentChanged; public Activity SetStatus(ActivityStatusCode code, [System.Runtime.CompilerServices.Nullable(2)] string description = null) { _statusCode = code; _statusDescription = ((code == ActivityStatusCode.Error) ? description : null); return this; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 0, 1, 2 })] public Enumerator<KeyValuePair<string, object>> EnumerateTagObjects() { return new Enumerator<KeyValuePair<string, object>>(_tags?.First); } [System.Runtime.CompilerServices.NullableContext(0)] public Enumerator<ActivityEvent> EnumerateEvents() { DiagLinkedList<ActivityEvent> events = _events; return new Enumerator<ActivityEvent>((events != null) ? events.First : null); } [System.Runtime.CompilerServices.NullableContext(0)] public Enumerator<ActivityLink> EnumerateLinks() { DiagLinkedList<ActivityLink> links = _links; return new Enumerator<ActivityLink>((links != null) ? links.First : null); } [return: System.Runtime.CompilerServices.Nullable(2)] public string GetBaggageItem(string key) { foreach (KeyValuePair<string, string> item in Baggage) { if (key == item.Key) return item.Value; } return null; } [return: System.Runtime.CompilerServices.Nullable(2)] public object GetTagItem(string key) { return _tags?.Get(key) ?? null; } public Activity(string operationName) { Source = s_defaultSource; IsAllDataRequested = true; if (string.IsNullOrEmpty(operationName)) NotifyError(new ArgumentException(System.SR.OperationNameInvalid)); OperationName = operationName; } public Activity AddTag(string key, [System.Runtime.CompilerServices.Nullable(2)] string value) { return AddTag(key, (object)value); } public Activity AddTag(string key, [System.Runtime.CompilerServices.Nullable(2)] object value) { KeyValuePair<string, object> keyValuePair = new KeyValuePair<string, object>(key, value); if (_tags != null || Interlocked.CompareExchange(ref _tags, new TagsLinkedList(keyValuePair, false), null) != null) _tags.Add(keyValuePair); return this; } public Activity SetTag(string key, [System.Runtime.CompilerServices.Nullable(2)] object value) { KeyValuePair<string, object> keyValuePair = new KeyValuePair<string, object>(key, value); if (_tags != null || Interlocked.CompareExchange(ref _tags, new TagsLinkedList(keyValuePair, true), null) != null) _tags.Set(keyValuePair); return this; } public Activity AddEvent(ActivityEvent e) { if (_events != null || Interlocked.CompareExchange(ref _events, new DiagLinkedList<ActivityEvent>(e), null) != null) _events.Add(e); return this; } public Activity AddBaggage(string key, [System.Runtime.CompilerServices.Nullable(2)] string value) { KeyValuePair<string, string> keyValuePair = new KeyValuePair<string, string>(key, value); if (_baggage != null || Interlocked.CompareExchange(ref _baggage, new BaggageLinkedList(keyValuePair, false), null) != null) _baggage.Add(keyValuePair); return this; } public Activity SetBaggage(string key, [System.Runtime.CompilerServices.Nullable(2)] string value) { KeyValuePair<string, string> keyValuePair = new KeyValuePair<string, string>(key, value); if (_baggage != null || Interlocked.CompareExchange(ref _baggage, new BaggageLinkedList(keyValuePair, true), null) != null) _baggage.Set(keyValuePair); return this; } public Activity SetParentId(string parentId) { if (Parent != null) NotifyError(new InvalidOperationException(System.SR.SetParentIdOnActivityWithParent)); else if (ParentId != null || _parentSpanId != null) { NotifyError(new InvalidOperationException(System.SR.ParentIdAlreadySet)); } else if (string.IsNullOrEmpty(parentId)) { NotifyError(new ArgumentException(System.SR.ParentIdInvalid)); } else { _parentId = parentId; } return this; } public Activity SetParentId(ActivityTraceId traceId, ActivitySpanId spanId, ActivityTraceFlags activityTraceFlags = ActivityTraceFlags.None) { if (Parent != null) NotifyError(new InvalidOperationException(System.SR.SetParentIdOnActivityWithParent)); else if (ParentId != null || _parentSpanId != null) { NotifyError(new InvalidOperationException(System.SR.ParentIdAlreadySet)); } else { _traceId = traceId.ToHexString(); _parentSpanId = spanId.ToHexString(); ActivityTraceFlags = activityTraceFlags; _parentTraceFlags = (byte)activityTraceFlags; } return this; } public Activity SetStartTime(DateTime startTimeUtc) { if (startTimeUtc.Kind != DateTimeKind.Utc) NotifyError(new InvalidOperationException(System.SR.StartTimeNotUtc)); else StartTimeUtc = startTimeUtc; return this; } public Activity SetEndTime(DateTime endTimeUtc) { if (endTimeUtc.Kind != DateTimeKind.Utc) NotifyError(new InvalidOperationException(System.SR.EndTimeNotUtc)); else { Duration = endTimeUtc - StartTimeUtc; if (Duration.Ticks <= 0) Duration = new TimeSpan(1); } return this; } public Activity Start() { if (_id != null || _spanId != null) NotifyError(new InvalidOperationException(System.SR.ActivityStartAlreadyStarted)); else { _previousActiveActivity = Current; if (_parentId == null && _parentSpanId == null && _previousActiveActivity != null) Parent = _previousActiveActivity; if (StartTimeUtc == default(DateTime)) StartTimeUtc = GetUtcNow(); if (IdFormat == ActivityIdFormat.Unknown) IdFormat = (ForceDefaultIdFormat ? DefaultIdFormat : ((Parent != null) ? Parent.IdFormat : ((_parentSpanId != null) ? ActivityIdFormat.W3C : ((_parentId == null) ? DefaultIdFormat : ((!IsW3CId(_parentId)) ? ActivityIdFormat.Hierarchical : ActivityIdFormat.W3C))))); if (IdFormat == ActivityIdFormat.W3C) GenerateW3CId(); else _id = GenerateHierarchicalId(); SetCurrent(this); Source.NotifyActivityStart(this); } return this; } public void Stop() { if (_id == null && _spanId == null) NotifyError(new InvalidOperationException(System.SR.ActivityNotStarted)); else if (!IsStopped) { IsStopped = true; if (Duration == TimeSpan.Zero) SetEndTime(GetUtcNow()); Source.NotifyActivityStop(this); SetCurrent(_previousActiveActivity); } } public Activity SetIdFormat(ActivityIdFormat format) { if (_id != null || _spanId != null) NotifyError(new InvalidOperationException(System.SR.SetFormatOnStartedActivity)); else IdFormat = format; return this; } private static bool IsW3CId(string id) { if (id.Length == 55 && (('0' <= id[0] && id[0] <= '9') || ('a' <= id[0] && id[0] <= 'f')) && (('0' <= id[1] && id[1] <= '9') || ('a' <= id[1] && id[1] <= 'f'))) { if (id[0] == 'f') return id[1] != 'f'; return true; } return false; } internal static bool TryConvertIdToContext(string traceParent, string traceState, bool isRemote, out ActivityContext context) { context = default(ActivityContext); if (!IsW3CId(traceParent)) return false; ReadOnlySpan<char> idData = traceParent.AsSpan(3, 32); ReadOnlySpan<char> idData2 = traceParent.AsSpan(36, 16); if (!ActivityTraceId.IsLowerCaseHexAndNotAllZeros(idData) || !ActivityTraceId.IsLowerCaseHexAndNotAllZeros(idData2) || !System.HexConverter.IsHexLowerChar(traceParent[53]) || !System.HexConverter.IsHexLowerChar(traceParent[54])) return false; context = new ActivityContext(new ActivityTraceId(idData.ToString()), new ActivitySpanId(idData2.ToString()), (ActivityTraceFlags)ActivityTraceId.HexByteFromChars(traceParent[53], traceParent[54]), traceState, isRemote); return true; } public void Dispose() { if (!IsStopped) Stop(); Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { } public void SetCustomProperty(string propertyName, [System.Runtime.CompilerServices.Nullable(2)] object propertyValue) { if (_customProperties == null) Interlocked.CompareExchange(ref _customProperties, new Dictionary<string, object>(), null); lock (_customProperties) { if (propertyValue == null) _customProperties.Remove(propertyName); else _customProperties[propertyName] = propertyValue; } } [return: System.Runtime.CompilerServices.Nullable(2)] public object GetCustomProperty(string propertyName) { if (_customProperties == null) return null; lock (_customProperties) { object value; return _customProperties.TryGetValue(propertyName, out value) ? value : null; } } internal static Activity Create(ActivitySource source, string name, ActivityKind kind, string parentId, ActivityContext parentContext, IEnumerable<KeyValuePair<string, object>> tags, IEnumerable<ActivityLink> links, DateTimeOffset startTime, ActivityTagsCollection samplerTags, ActivitySamplingResult request, bool startIt, ActivityIdFormat idFormat, string traceState) { Activity activity = new Activity(name); activity.Source = source; activity.Kind = kind; activity.IdFormat = idFormat; activity._traceState = traceState; if (links != null) { using (IEnumerator<ActivityLink> enumerator = links.GetEnumerator()) { if (enumerator.MoveNext()) activity._links = new DiagLinkedList<ActivityLink>(enumerator); } } if (tags != null) { using (IEnumerator<KeyValuePair<string, object>> enumerator2 = tags.GetEnumerator()) { if (enumerator2.MoveNext()) activity._tags = new TagsLinkedList(enumerator2); } } if (samplerTags != null) { if (activity._tags == null) activity._tags = new TagsLinkedList(samplerTags); else activity._tags.Add(samplerTags); } if (parentId != null) activity._parentId = parentId; else if (parentContext != default(ActivityContext)) { activity._traceId = parentContext.TraceId.ToString(); ActivitySpanId spanId = parentContext.SpanId; ActivitySpanId spandId = default(ActivitySpanId); if (spanId != spandId) { Activity activity2 = activity; spandId = parentContext.SpanId; activity2._parentSpanId = spandId.ToString(); } activity.ActivityTraceFlags = parentContext.TraceFlags; activity._parentTraceFlags = (byte)parentContext.TraceFlags; activity.HasRemoteParent = parentContext.IsRemote; } activity.IsAllDataRequested = (request == ActivitySamplingResult.AllData || request == ActivitySamplingResult.AllDataAndRecorded); if (request == ActivitySamplingResult.AllDataAndRecorded) activity.ActivityTraceFlags |= ActivityTraceFlags.Recorded; if (startTime != default(DateTimeOffset)) activity.StartTimeUtc = startTime.UtcDateTime; if (startIt) activity.Start(); return activity; } private void GenerateW3CId() { if (_traceId == null && !TrySetTraceIdFromParent()) _traceId = (TraceIdGenerator?.Invoke() ?? ActivityTraceId.CreateRandom()).ToHexString(); if (!W3CIdFlagsSet) TrySetTraceFlagsFromParent(); _spanId = ActivitySpanId.CreateRandom().ToHexString(); } private static void NotifyError(Exception exception) { try { throw exception; } catch { } } private string GenerateHierarchicalId() { if (Parent == null) { if (ParentId == null) return GenerateRootId(); string text = (ParentId[0] == '|') ? ParentId : ("|" + ParentId); char c = text[text.Length - 1]; if (c != '.' && c != '_') text += "."; return AppendSuffix(text, Interlocked.Increment(ref s_currentRootId).ToString("x"), '_'); } return AppendSuffix(Parent.Id, Interlocked.Increment(ref Parent._currentChildId).ToString(), '.'); } private string GetRootId(string id) { if (IdFormat == ActivityIdFormat.W3C) return id.Substring(3, 32); int num = id.IndexOf('.'); if (num < 0) num = id.Length; int num2 = (id[0] == '|') ? 1 : 0; return id.Substring(num2, num - num2); } private string AppendSuffix(string parentId, string suffix, char delimiter) { if (parentId.Length + suffix.Length < 1024) return parentId + suffix + delimiter.ToString(); int num = 1015; while (num > 1 && parentId[num - 1] != '.' && parentId[num - 1] != '_') { num--; } if (num == 1) return GenerateRootId(); string str = ((int)GetRandomNumber()).ToString("x8"); return parentId.Substring(0, num) + str + "#"; } private unsafe static long GetRandomNumber() { Guid guid = Guid.NewGuid(); return *(long*)(&guid); } private static bool ValidateSetCurrent(Activity activity) { bool flag = activity == null || (activity.Id != null && !activity.IsStopped); if (!flag) NotifyError(new InvalidOperationException(System.SR.ActivityNotRunning)); return flag; } private bool TrySetTraceIdFromParent() { ActivityTraceId activityTraceId; if (Parent != null && Parent.IdFormat == ActivityIdFormat.W3C) { activityTraceId = Parent.TraceId; _traceId = activityTraceId.ToHexString(); } else if (_parentId != null && IsW3CId(_parentId)) { try { activityTraceId = ActivityTraceId.CreateFromString(_parentId.AsSpan(3, 32)); _traceId = activityTraceId.ToHexString(); } catch { } } return _traceId != null; } private void TrySetTraceFlagsFromParent() { if (!W3CIdFlagsSet) { if (Parent != null) ActivityTraceFlags = Parent.ActivityTraceFlags; else if (_parentId != null && IsW3CId(_parentId)) { if (System.HexConverter.IsHexLowerChar(_parentId[53]) && System.HexConverter.IsHexLowerChar(_parentId[54])) _w3CIdFlags = (byte)(ActivityTraceId.HexByteFromChars(_parentId[53], _parentId[54]) | 128); else _w3CIdFlags = 128; } } } private static void SetCurrent(Activity activity) { Activity value = s_current.Value; s_current.Value = activity; Activity.CurrentChanged?.Invoke(null, new ActivityChangedEventArgs(value, activity)); } private static string GenerateRootId() { return "|" + Interlocked.Increment(ref s_currentRootId).ToString("x") + s_uniqSuffix; } internal static DateTime GetUtcNow() { return DateTime.UtcNow; } } }