< Summary

Class:Azure.Core.Pipeline.ActivityExtensions
Assembly:Azure.Messaging.ServiceBus
File(s):C:\Git\azure-sdk-for-net\sdk\core\Azure.Core\src\Shared\DiagnosticScope.cs
Covered lines:5
Uncovered lines:8
Coverable lines:13
Total lines:167
Line coverage:38.4% (5 of 13)
Covered branches:3
Total branches:12
Branch coverage:25% (3 of 12)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.cctor()-100%50%
SetW3CFormat(...)-66.67%50%
IsW3CFormat(...)-0%0%
TryGetTraceState(...)-0%0%

File(s)

C:\Git\azure-sdk-for-net\sdk\core\Azure.Core\src\Shared\DiagnosticScope.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4#nullable enable
 5
 6using System;
 7using System.Collections.Generic;
 8using System.Diagnostics;
 9using System.Reflection;
 10
 11namespace Azure.Core.Pipeline
 12{
 13    internal readonly struct DiagnosticScope : IDisposable
 14    {
 15        private readonly DiagnosticActivity? _activity;
 16
 17        private readonly string _name;
 18
 19        private readonly DiagnosticListener _source;
 20
 21        internal DiagnosticScope(string name, DiagnosticListener source)
 22        {
 23            _name = name;
 24            _source = source;
 25            _activity = _source.IsEnabled(_name) ? new DiagnosticActivity(_name) : null;
 26            _activity?.SetW3CFormat();
 27        }
 28
 29        public bool IsEnabled => _activity != null;
 30
 31        public void AddAttribute(string name, string value)
 32        {
 33            _activity?.AddTag(name, value);
 34        }
 35
 36        public void AddAttribute<T>(string name, T value)
 37        {
 38            if (_activity != null && value != null)
 39            {
 40                AddAttribute(name, value.ToString() ?? string.Empty);
 41            }
 42        }
 43
 44        public void AddAttribute<T>(string name, T value, Func<T, string> format)
 45        {
 46            if (_activity != null)
 47            {
 48                AddAttribute(name, format(value));
 49            }
 50        }
 51
 52        public void AddLink(string id, IDictionary<string, string>? attributes = null)
 53        {
 54            if (_activity != null)
 55            {
 56                var linkedActivity = new Activity("LinkedActivity");
 57                linkedActivity.SetW3CFormat();
 58                linkedActivity.SetParentId(id);
 59
 60                if (attributes != null)
 61                {
 62                    foreach (var kvp in attributes)
 63                    {
 64                        linkedActivity.AddTag(kvp.Key, kvp.Value);
 65                    }
 66                }
 67
 68                _activity.AddLink(linkedActivity);
 69            }
 70        }
 71
 72        public void Start()
 73        {
 74            if (_activity != null)
 75            {
 76                _source.StartActivity(_activity, _activity);
 77            }
 78        }
 79
 80        public void SetStartTime(DateTime dateTime) => _activity?.SetStartTime(dateTime);
 81
 82        public void Dispose()
 83        {
 84            if (_activity == null)
 85            {
 86                return;
 87            }
 88
 89            if (_source != null)
 90            {
 91                _source.StopActivity(_activity, null);
 92            }
 93            else
 94            {
 95                _activity?.Stop();
 96            }
 97        }
 98
 99        public void Failed(Exception e)
 100        {
 101            if (_activity == null)
 102            {
 103                return;
 104            }
 105
 106            _source?.Write(_activity.OperationName + ".Exception", e);
 107
 108        }
 109
 110        private class DiagnosticActivity : Activity
 111        {
 112            private List<Activity>? _links;
 113
 114            public IEnumerable<Activity> Links => (IEnumerable<Activity>?)_links ?? Array.Empty<Activity>();
 115
 116            public DiagnosticActivity(string operationName) : base(operationName)
 117            {
 118            }
 119
 120            public void AddLink(Activity activity)
 121            {
 122                _links ??= new List<Activity>();
 123                _links.Add(activity);
 124            }
 125        }
 126    }
 127
 128    /// <summary>
 129    /// HACK HACK HACK. Some runtime environments like Azure.Functions downgrade System.Diagnostic.DiagnosticSource pack
 130    /// This type is a temporary workaround to avoid the issue.
 131    /// </summary>
 132    internal static class ActivityExtensions
 133    {
 2134        private static readonly MethodInfo? s_setIdFormatMethod = typeof(Activity).GetMethod("SetIdFormat");
 2135        private static readonly MethodInfo? s_getIdFormatMethod = typeof(Activity).GetProperty("IdFormat")?.GetMethod;
 2136        private static readonly MethodInfo? s_getTraceStateStringMethod = typeof(Activity).GetProperty("TraceStateString
 137
 138        public static bool SetW3CFormat(this Activity activity)
 139        {
 0140            if (s_setIdFormatMethod == null) return false;
 141
 336142            s_setIdFormatMethod.Invoke(activity, new object[]{ 2 /* ActivityIdFormat.W3C */});
 143
 336144            return true;
 145        }
 146
 147        public static bool IsW3CFormat(this Activity activity)
 148        {
 0149            if (s_getIdFormatMethod == null) return false;
 150
 0151            object? result = s_getIdFormatMethod.Invoke(activity, Array.Empty<object>());
 152
 0153            return result != null && (int)result == 2 /* ActivityIdFormat.W3C */;
 154        }
 155
 156        public static bool TryGetTraceState(this Activity activity, out string? traceState)
 157        {
 0158            traceState = null;
 159
 0160            if (s_getTraceStateStringMethod == null) return false;
 161
 0162            traceState = s_getTraceStateStringMethod.Invoke(activity, Array.Empty<object>()) as string;
 163
 0164            return true;
 165        }
 166    }
 167}