< Summary

Class:Azure.Core.Pipeline.ClientDiagnostics
Assembly:Azure.ResourceManager.Resources
File(s):C:\Git\azure-sdk-for-net\sdk\core\Azure.Core\src\Shared\ClientDiagnostics.cs
Covered lines:49
Uncovered lines:22
Coverable lines:71
Total lines:192
Line coverage:69% (49 of 71)
Covered branches:21
Total branches:32
Branch coverage:65.6% (21 of 32)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor(...)-100%100%
CreateRequestFailedExceptionAsync()-100%100%
CreateRequestFailedException(...)-100%100%
CreateRequestFailedExceptionWithContent(...)-66.67%25%
CreateRequestFailedMessageAsync(...)-0%100%
CreateRequestFailedMessage(...)-0%100%
CreateRequestFailedMessageAsync()-0%100%
CreateRequestFailedMessageWithContent(...)-58.82%62.5%
ReadContentAsync()-100%100%
GetResourceProviderNamespace(...)-80%66.67%

File(s)

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

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.Diagnostics;
 7using System.Globalization;
 8using System.IO;
 9using System.Linq;
 10using System.Reflection;
 11using System.Text;
 12using System.Threading.Tasks;
 13using Azure.Core.Pipeline;
 14
 15#nullable enable
 16
 17namespace Azure.Core.Pipeline
 18{
 19    internal sealed partial class ClientDiagnostics : DiagnosticScopeFactory
 20    {
 21        private const string DefaultMessage = "Service request failed.";
 22
 23        private readonly HttpMessageSanitizer _sanitizer;
 56424        public ClientDiagnostics(ClientOptions options) : base(
 56425            options.GetType().Namespace!,
 56426            GetResourceProviderNamespace(options.GetType().Assembly),
 56427            options.Diagnostics.IsDistributedTracingEnabled)
 28        {
 56429            _sanitizer = new HttpMessageSanitizer(
 56430                options.Diagnostics.LoggedQueryParameters.ToArray(),
 56431                options.Diagnostics.LoggedHeaderNames.ToArray());
 56432        }
 33
 34        /// <summary>
 35        /// Partial method that can optionally be defined to extract the error
 36        /// message, code, and details in a service specific manner.
 37        /// </summary>
 38        /// <param name="content">The error content.</param>
 39        /// <param name="message">The error message.</param>
 40        /// <param name="errorCode">The error code.</param>
 41        /// <param name="additionalInfo">Additional error details.</param>
 42        partial void ExtractFailureContent(
 43            string? content,
 44            ref string? message,
 45            ref string? errorCode,
 46            ref IDictionary<string, string>? additionalInfo);
 47
 48        public async ValueTask<RequestFailedException> CreateRequestFailedExceptionAsync(Response response, string? mess
 49        {
 5450            var content = await ReadContentAsync(response, true).ConfigureAwait(false);
 51            ExtractFailureContent(content, ref message, ref errorCode, ref additionalInfo);
 5452            return CreateRequestFailedExceptionWithContent(response, message, content, errorCode, additionalInfo, innerE
 5453        }
 54
 55        public RequestFailedException CreateRequestFailedException(Response response, string? message = null, string? er
 56        {
 7057            string? content = ReadContentAsync(response, false).EnsureCompleted();
 58            ExtractFailureContent(content, ref message, ref errorCode, ref additionalInfo);
 7059            return CreateRequestFailedExceptionWithContent(response, message, content, errorCode, additionalInfo, innerE
 60        }
 61
 62        public RequestFailedException CreateRequestFailedExceptionWithContent(
 63            Response response,
 64            string? message = null,
 65            string? content = null,
 66            string? errorCode = null,
 67            IDictionary<string, string>? additionalInfo = null,
 68            Exception? innerException = null)
 69        {
 12470            var formatMessage = CreateRequestFailedMessageWithContent(response, message, content, errorCode, additionalI
 12471            var exception = new RequestFailedException(response.Status, formatMessage, errorCode, innerException);
 72
 12473            if (additionalInfo != null)
 74            {
 075                foreach (KeyValuePair<string, string> keyValuePair in additionalInfo)
 76                {
 077                    exception.Data.Add(keyValuePair.Key, keyValuePair.Value);
 78                }
 79            }
 80
 12481            return exception;
 82        }
 83
 84        public ValueTask<string> CreateRequestFailedMessageAsync(Response response, string? message = null, string? erro
 85        {
 086            return CreateRequestFailedMessageAsync(response, message, errorCode, additionalInfo, true);
 87        }
 88
 89        public string CreateRequestFailedMessage(Response response, string? message = null, string? errorCode = null, ID
 90        {
 091            return CreateRequestFailedMessageAsync(response, message, errorCode, additionalInfo, false).EnsureCompleted(
 92        }
 93
 94        private async ValueTask<string> CreateRequestFailedMessageAsync(Response response, string? message, string? erro
 95        {
 096            var content = await ReadContentAsync(response, async).ConfigureAwait(false);
 97
 098            return CreateRequestFailedMessageWithContent(response, message, content, errorCode, additionalInfo);
 099        }
 100
 101        public string CreateRequestFailedMessageWithContent(Response response, string? message, string? content, string?
 102        {
 124103            StringBuilder messageBuilder = new StringBuilder()
 124104                .AppendLine(message ?? DefaultMessage)
 124105                .Append("Status: ")
 124106                .Append(response.Status.ToString(CultureInfo.InvariantCulture));
 107
 124108            if (!string.IsNullOrEmpty(response.ReasonPhrase))
 109            {
 0110                messageBuilder.Append(" (")
 0111                    .Append(response.ReasonPhrase)
 0112                    .AppendLine(")");
 113            }
 114            else
 115            {
 124116                messageBuilder.AppendLine();
 117            }
 118
 124119            if (!string.IsNullOrWhiteSpace(errorCode))
 120            {
 0121                messageBuilder.Append("ErrorCode: ")
 0122                    .Append(errorCode)
 0123                    .AppendLine();
 124            }
 125
 124126            if (additionalInfo != null && additionalInfo.Count > 0)
 127            {
 0128                messageBuilder
 0129                    .AppendLine()
 0130                    .AppendLine("Additional Information:");
 0131                foreach (KeyValuePair<string, string> info in additionalInfo)
 132                {
 0133                    messageBuilder
 0134                        .Append(info.Key)
 0135                        .Append(": ")
 0136                        .AppendLine(info.Value);
 137                }
 138            }
 139
 124140            if (content != null)
 141            {
 116142                messageBuilder
 116143                    .AppendLine()
 116144                    .AppendLine("Content:")
 116145                    .AppendLine(content);
 146            }
 147
 124148            messageBuilder
 124149                .AppendLine()
 124150                .AppendLine("Headers:");
 151
 2872152            foreach (HttpHeader responseHeader in response.Headers)
 153            {
 1312154                string headerValue = _sanitizer.SanitizeHeader(responseHeader.Name, responseHeader.Value);
 1312155                messageBuilder.AppendLine($"{responseHeader.Name}: {headerValue}");
 156            }
 157
 124158            return messageBuilder.ToString();
 159        }
 160
 161        private static async ValueTask<string?> ReadContentAsync(Response response, bool async)
 162        {
 124163            string? content = null;
 164
 124165            if (response.ContentStream != null &&
 124166                ContentTypeUtilities.TryGetTextEncoding(response.Headers.ContentType, out var encoding))
 167            {
 116168                using (var streamReader = new StreamReader(response.ContentStream, encoding))
 169                {
 116170                    content = async ? await streamReader.ReadToEndAsync().ConfigureAwait(false) : streamReader.ReadToEnd
 116171                }
 172            }
 173
 124174            return content;
 124175        }
 176
 177        internal static string? GetResourceProviderNamespace(Assembly assembly)
 178        {
 6204179            foreach (var customAttribute in assembly.GetCustomAttributes(true))
 180            {
 181                // Weak bind internal shared type
 2820182                var attributeType = customAttribute.GetType();
 2820183                if (attributeType.Name == "AzureResourceProviderNamespaceAttribute")
 184                {
 564185                    return attributeType.GetProperty("ResourceProviderNamespace")?.GetValue(customAttribute) as string;
 186                }
 187            }
 188
 0189            return null;
 190        }
 191    }
 192}