| File: HttpExceptionSummaryProvider.cs | Web Access |
| Project: src\src\Libraries\Microsoft.Extensions.Diagnostics.ExceptionSummarization\Microsoft.Extensions.Diagnostics.ExceptionSummarization.csproj (Microsoft.Extensions.Diagnostics.ExceptionSummarization) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Frozen; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Net; using System.Net.Sockets; using System.Threading.Tasks; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.Diagnostics.ExceptionSummarization; /// <summary> /// Http exception diagnosis for telemetry. /// </summary> internal sealed class HttpExceptionSummaryProvider : IExceptionSummaryProvider { private const int DefaultDescriptionIndex = -1; private const string TaskCanceled = "TaskCanceled"; private const string TaskTimeout = "TaskTimeout"; private static readonly FrozenDictionary<WebExceptionStatus, int> _webExceptionStatusMap; private static readonly FrozenDictionary<SocketError, int> _socketErrorMap; private static readonly ImmutableArray<string> _descriptions; [SuppressMessage("Performance", "CA1810:Initialize reference type static fields inline", Justification = "Can't do this since the field values are interdependent")] static HttpExceptionSummaryProvider() { var descriptions = new List<string> { TaskCanceled, TaskTimeout }; var socketErrors = new Dictionary<SocketError, int>(); #if NET5_0_OR_GREATER foreach (var socketError in Enum.GetValues<SocketError>()) { #else foreach (var v in Enum.GetValues(typeof(SocketError))) { var socketError = (SocketError)v!; #endif var name = socketError.ToString(); socketErrors[socketError] = descriptions.Count; descriptions.Add(name); } var webStatuses = new Dictionary<WebExceptionStatus, int>(); #if NET5_0_OR_GREATER foreach (var status in Enum.GetValues<WebExceptionStatus>()) { #else foreach (var v in Enum.GetValues(typeof(WebExceptionStatus))) { var status = (WebExceptionStatus)v!; #endif var name = status.ToString(); webStatuses[status] = descriptions.Count; descriptions.Add(name); } _descriptions = descriptions.ToImmutableArray(); _socketErrorMap = socketErrors.ToFrozenDictionary(); _webExceptionStatusMap = webStatuses.ToFrozenDictionary(); } public IEnumerable<Type> SupportedExceptionTypes { get; } = new[] { typeof(TaskCanceledException), typeof(OperationCanceledException), typeof(WebException), typeof(SocketException), }; public IReadOnlyList<string> Descriptions => _descriptions; public int Describe(Exception exception, out string? additionalDetails) { _ = Throw.IfNull(exception); additionalDetails = null; switch (exception) { case OperationCanceledException ex: { return ex.CancellationToken.IsCancellationRequested ? 0 : 1; } case WebException ex: { if (_webExceptionStatusMap.TryGetValue(ex.Status, out var index)) { return index; } break; } case SocketException ex: { if (_socketErrorMap.TryGetValue(ex.SocketErrorCode, out var index)) { return index; } break; } } return DefaultDescriptionIndex; } }