| File: ExceptionSummarizer.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 Microsoft.Shared.Diagnostics; using Microsoft.Shared.Text; namespace Microsoft.Extensions.Diagnostics.ExceptionSummarization; internal sealed class ExceptionSummarizer : IExceptionSummarizer { private const string DefaultDescription = "Unknown"; private readonly FrozenDictionary<Type, IExceptionSummaryProvider> _exceptionTypesToProviders; public ExceptionSummarizer(IEnumerable<IExceptionSummaryProvider> providers) { var exceptionTypesToProvidersBuilder = new Dictionary<Type, IExceptionSummaryProvider>(); foreach (var exceptionSummaryProvider in providers) { foreach (var exceptionType in exceptionSummaryProvider.SupportedExceptionTypes) { exceptionTypesToProvidersBuilder.Add(exceptionType, exceptionSummaryProvider); } } _exceptionTypesToProviders = exceptionTypesToProvidersBuilder.ToFrozenDictionary(); } public ExceptionSummary Summarize(Exception exception) { _ = Throw.IfNull(exception); var exceptionType = exception.GetType(); var exceptionTypeName = exceptionType.Name; // find a match for the exception type or a base type thereof var type = exceptionType; while (type != null) { if (_exceptionTypesToProviders.TryGetValue(type, out var exceptionSummaryProvider)) { return BuildSummary(exception, exceptionSummaryProvider, exceptionTypeName); } type = type.BaseType; } // Let's see if we get lucky with the inner exception if (exception.InnerException != null) { var innerExceptionType = exception.InnerException.GetType(); if (_exceptionTypesToProviders.TryGetValue(innerExceptionType, out var innerExceptionSummaryProvider)) { return BuildSummary( exception.InnerException, innerExceptionSummaryProvider, $"{exceptionTypeName}->{innerExceptionType.Name}"); } } // Now let's see if we can get something from Exception HResult var hresult = exception.HResult; var exceptionDescription = exception.InnerException != null ? exception.InnerException.GetType().Name : DefaultDescription; if (hresult != default) { return new ExceptionSummary( exceptionTypeName, exceptionDescription, hresult.ToInvariantString()); } // final recourse, generate a default message return new ExceptionSummary( exceptionTypeName, exceptionDescription, DefaultDescription); } private static ExceptionSummary BuildSummary( Exception exception, IExceptionSummaryProvider exceptionSummaryProvider, string exceptionType) { var descriptionIndex = exceptionSummaryProvider.Describe(exception, out var additionalDetails); if (descriptionIndex >= exceptionSummaryProvider.Descriptions.Count || descriptionIndex < 0) { return new ExceptionSummary( exceptionType, DefaultDescription, $"Exception summary provider {exceptionSummaryProvider.GetType().Name} returned invalid short description index {descriptionIndex}"); } return new ExceptionSummary(exceptionType, exceptionSummaryProvider.Descriptions[descriptionIndex], additionalDetails ?? DefaultDescription); } }