<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="4.6.0-preview3.19128.7" />

Activity

public class Activity
using System.Collections.Generic; using System.Threading; namespace System.Diagnostics { public class Activity { private class KeyValueListNode { public KeyValuePair<string, string> keyValue; public KeyValueListNode Next; } private string _rootId; private int _currentChildId; private static readonly string s_uniqSuffix = "-" + GetRandomNumber().ToString("x") + "."; private static long s_currentRootId = (uint)GetRandomNumber(); private const int RequestIdMaxLength = 1024; private KeyValueListNode _tags; private KeyValueListNode _baggage; private bool isFinished; private static readonly AsyncLocal<Activity> s_current = new AsyncLocal<Activity>(); public string OperationName { get; } public string Id { get; set; } public DateTime StartTimeUtc { get; set; } public Activity Parent { get; set; } public string ParentId { get; set; } public string RootId { get { if (_rootId == null) { if (Id != null) _rootId = GetRootId(Id); else if (ParentId != null) { _rootId = GetRootId(ParentId); } } return _rootId; } } public IEnumerable<KeyValuePair<string, string>> Tags { get { for (KeyValueListNode tags = _tags; tags != null; tags = tags.Next) { yield return tags.keyValue; } } } public IEnumerable<KeyValuePair<string, string>> Baggage { get { for (Activity activity = this; activity != null; activity = activity.Parent) { for (KeyValueListNode baggage = activity._baggage; baggage != null; baggage = baggage.Next) { yield return baggage.keyValue; } } } } public TimeSpan Duration { get; set; } public static Activity Current { get { return s_current.Value; } set { if (ValidateSetCurrent(value)) SetCurrent(value); } } public string GetBaggageItem(string key) { foreach (KeyValuePair<string, string> item in Baggage) { if (key == item.Key) return item.Value; } return null; } public Activity(string operationName) { if (string.IsNullOrEmpty(operationName)) NotifyError(new ArgumentException("operationName must not be null or empty")); else OperationName = operationName; } public Activity AddTag(string key, string value) { _tags = new KeyValueListNode { keyValue = new KeyValuePair<string, string>(key, value), Next = _tags }; return this; } public Activity AddBaggage(string key, string value) { _baggage = new KeyValueListNode { keyValue = new KeyValuePair<string, string>(key, value), Next = _baggage }; return this; } public Activity SetParentId(string parentId) { if (Parent != null) NotifyError(new InvalidOperationException("Trying to set ParentId on activity which has Parent")); else if (ParentId != null) { NotifyError(new InvalidOperationException("ParentId is already set")); } else if (string.IsNullOrEmpty(parentId)) { NotifyError(new ArgumentException("parentId must not be null or empty")); } else { ParentId = parentId; } return this; } public Activity SetStartTime(DateTime startTimeUtc) { if (startTimeUtc.Kind != DateTimeKind.Utc) NotifyError(new InvalidOperationException("startTimeUtc is not UTC")); else StartTimeUtc = startTimeUtc; return this; } public Activity SetEndTime(DateTime endTimeUtc) { if (endTimeUtc.Kind != DateTimeKind.Utc) NotifyError(new InvalidOperationException("endTimeUtc is not UTC")); else { Duration = endTimeUtc - StartTimeUtc; if (Duration.Ticks <= 0) Duration = new TimeSpan(1); } return this; } public Activity Start() { if (Id != null) NotifyError(new InvalidOperationException("Trying to start an Activity that was already started")); else { if (ParentId == null) { Activity current = Current; if (current != null) { ParentId = current.Id; Parent = current; } } if (StartTimeUtc == default(DateTime)) StartTimeUtc = GetUtcNow(); Id = GenerateId(); SetCurrent(this); } return this; } public void Stop() { if (Id == null) NotifyError(new InvalidOperationException("Trying to stop an Activity that was not started")); else if (!isFinished) { isFinished = true; if (Duration == TimeSpan.Zero) SetEndTime(GetUtcNow()); SetCurrent(Parent); } } private static void NotifyError(Exception exception) { try { throw exception; } catch { } } private string GenerateId() { 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) { 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 string GenerateRootId() { return "|" + Interlocked.Increment(ref s_currentRootId).ToString("x") + s_uniqSuffix; } 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.isFinished); if (!flag) NotifyError(new InvalidOperationException("Trying to set an Activity that is not running")); return flag; } private static void SetCurrent(Activity activity) { s_current.Value = activity; } internal static DateTime GetUtcNow() { return DateTime.UtcNow; } } }