using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Data;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Globalization;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Reflection;
using System.Resources;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Serilog.Configuration;
using Serilog.Core;
using Serilog.Events;
using Serilog.Exceptions.Core;
using Serilog.Exceptions.Destructurers;
using Serilog.Exceptions.Filters;
using Serilog.Exceptions.Reflection;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CLSCompliant(true)]
[assembly: InternalsVisibleTo("Serilog.Exceptions.Test, PublicKey=00240000048000009400000006020000002400005253413100040000010001007320f17cde01a37b8b3dff91961943f76893c63352544608de15974586e17739e0b232cdc8cc8762b40d988a21522024abca8116605ed1c8958f350bc6ca4594aa1ca61c1906d85ee76df8d9b404ffd65a5f6efeddd486bddd5b74ff9a7449af0dc9d43da753a3023b20ca616e8313e82a18719b6551f37c45c8d8e4e4cf9bac")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Muhammad Rehan Saeed (RehanSaeed.com)")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © Muhammad Rehan Saeed. All rights Reserved")]
[assembly: AssemblyDescription("Log exception details and custom properties that are not output in Exception.ToString().")]
[assembly: AssemblyFileVersion("8.4.0.0")]
[assembly: AssemblyInformationalVersion("8.4.0+build.694.98b7a4b8790544615bd7afd38c81639bff394081")]
[assembly: AssemblyProduct("Serilog Exceptions")]
[assembly: AssemblyTitle("Serilog.Exceptions")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/RehanSaeed/Serilog.Exceptions.git")]
[assembly: NeutralResourcesLanguage("en-GB")]
[assembly: AssemblyVersion("8.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace Serilog.Exceptions
{
internal static class DictionaryExtensions
{
public static Dictionary<string, object?> ToStringObjectDictionary(this IDictionary dictionary)
{
Dictionary<string, object> dictionary2 = new Dictionary<string, object>(dictionary.Count);
foreach (object key in dictionary.Keys)
{
if (key != null)
{
string text = key.ToString();
object value = dictionary[key];
if (text != null)
{
dictionary2.Add(text, value);
}
}
}
return dictionary2;
}
}
public static class LoggerEnrichmentConfigurationExtensions
{
public static LoggerConfiguration WithExceptionDetails(this LoggerEnrichmentConfiguration loggerEnrichmentConfiguration)
{
if (loggerEnrichmentConfiguration == null)
{
throw new ArgumentNullException("loggerEnrichmentConfiguration");
}
ExceptionEnricher exceptionEnricher = new ExceptionEnricher(new DestructuringOptionsBuilder().WithDefaultDestructurers().WithIgnoreStackTraceAndTargetSiteExceptionFilter());
return loggerEnrichmentConfiguration.With((ILogEventEnricher[])(object)new ILogEventEnricher[1] { exceptionEnricher });
}
public static LoggerConfiguration WithExceptionDetails(this LoggerEnrichmentConfiguration loggerEnrichmentConfiguration, IDestructuringOptions destructuringOptions)
{
if (loggerEnrichmentConfiguration == null)
{
throw new ArgumentNullException("loggerEnrichmentConfiguration");
}
ILogEventEnricher val = (ILogEventEnricher)(object)new ExceptionEnricher(destructuringOptions);
return loggerEnrichmentConfiguration.With((ILogEventEnricher[])(object)new ILogEventEnricher[1] { val });
}
}
[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[DebuggerNonUserCode]
[CompilerGenerated]
internal class Resources
{
private static ResourceManager resourceMan;
private static CultureInfo resourceCulture;
[EditorBrowsable(EditorBrowsableState.Advanced)]
internal static ResourceManager ResourceManager
{
get
{
if (resourceMan == null)
{
resourceMan = new ResourceManager("Serilog.Exceptions.Resources", typeof(Resources).GetTypeInfo().Assembly);
}
return resourceMan;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
internal static CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
internal static string CannotBeEmpty => ResourceManager.GetString("CannotBeEmpty", resourceCulture);
internal static string DestructuringDepthMustBeMoreThanZero => ResourceManager.GetString("DestructuringDepthMustBeMoreThanZero", resourceCulture);
internal static string FilterAlreadySet => ResourceManager.GetString("FilterAlreadySet", resourceCulture);
internal Resources()
{
}
}
internal static class TypeExtensions
{
public static TypeCode GetTypeCode(this Type type)
{
return Type.GetTypeCode(type);
}
}
}
namespace Serilog.Exceptions.Reflection
{
internal class ReflectionInfo
{
public ReflectionPropertyInfo[] Properties { get; }
public ReflectionPropertyInfo[] PropertiesExceptBaseOnes { get; }
public ReflectionInfo(ReflectionPropertyInfo[] properties, ReflectionPropertyInfo[] propertiesExceptBaseOnes)
{
Properties = properties;
PropertiesExceptBaseOnes = propertiesExceptBaseOnes;
}
}
internal class ReflectionInfoExtractor
{
private readonly ConcurrentDictionary<Type, ReflectionInfo> reflectionInfoCache = new ConcurrentDictionary<Type, ReflectionInfo>();
private readonly IList<PropertyInfo> baseExceptionPropertiesForDestructuring;
public ReflectionInfoExtractor()
{
baseExceptionPropertiesForDestructuring = GetExceptionPropertiesForDestructuring(typeof(Exception));
}
public ReflectionInfo GetOrCreateReflectionInfo(Type valueType)
{
return reflectionInfoCache.GetOrAdd(valueType, GenerateReflectionInfoForType);
}
private static Func<object, object> GenerateFastGetterForProperty(Type type, PropertyInfo property)
{
ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "num");
return Expression.Lambda<Func<object, object>>(Expression.Convert(Expression.Property(Expression.Convert(parameterExpression, type), property), typeof(object)), new ParameterExpression[1] { parameterExpression }).Compile();
}
private static List<PropertyInfo> GetExceptionPropertiesForDestructuring(Type valueType)
{
return (from x in valueType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
where x.CanRead && x.GetIndexParameters().Length == 0
select x).ToList();
}
private static void MarkRedefinedPropertiesWithFullName(ReflectionPropertyInfo[] propertyInfos)
{
Dictionary<string, List<ReflectionPropertyInfo>> dictionary = new Dictionary<string, List<ReflectionPropertyInfo>>();
foreach (ReflectionPropertyInfo reflectionPropertyInfo in propertyInfos)
{
if (dictionary.TryGetValue(reflectionPropertyInfo.Name, out var value))
{
value.Add(reflectionPropertyInfo);
continue;
}
dictionary[reflectionPropertyInfo.Name] = new List<ReflectionPropertyInfo> { reflectionPropertyInfo };
}
foreach (KeyValuePair<string, List<ReflectionPropertyInfo>> item in dictionary)
{
List<ReflectionPropertyInfo> value2 = item.Value;
if (value2.Count > 1)
{
FixGroupOfPropertiesWithConflictingNames(value2);
}
}
}
private static void FixGroupOfPropertiesWithConflictingNames(List<ReflectionPropertyInfo> properties)
{
foreach (ReflectionPropertyInfo property in properties)
{
foreach (ReflectionPropertyInfo property2 in properties)
{
property.MarkNameWithTypeNameIfRedefinesThatProperty(property2);
}
}
}
private ReflectionInfo GenerateReflectionInfoForType(Type valueType)
{
Type valueType2 = valueType;
ReflectionPropertyInfo[] array = (from p in GetExceptionPropertiesForDestructuring(valueType2)
select new ReflectionPropertyInfo(p.Name, p.DeclaringType, GenerateFastGetterForProperty(valueType2, p))).ToArray();
MarkRedefinedPropertiesWithFullName(array);
ReflectionPropertyInfo[] propertiesExceptBaseOnes = array.Where((ReflectionPropertyInfo p) => baseExceptionPropertiesForDestructuring.All((PropertyInfo bp) => bp.Name != p.Name)).ToArray();
return new ReflectionInfo(array, propertiesExceptBaseOnes);
}
}
internal class ReflectionPropertyInfo
{
private bool markedWithTypeName;
public string Name { get; private set; }
public Type? DeclaringType { get; }
public Func<object, object> Getter { get; }
public ReflectionPropertyInfo(string name, Type? declaringType, Func<object, object> getter)
{
Name = name;
DeclaringType = declaringType;
Getter = getter;
}
public void MarkNameWithTypeName()
{
if (!markedWithTypeName)
{
markedWithTypeName = true;
Name = DeclaringType?.Name + "." + Name;
}
}
public void MarkNameWithTypeNameIfRedefinesThatProperty(ReflectionPropertyInfo otherPropertyInfo)
{
if (otherPropertyInfo != this && !(DeclaringType == null) && !(otherPropertyInfo?.DeclaringType == null) && !(otherPropertyInfo?.Name != Name) && !markedWithTypeName && IsSubTypeOf(otherPropertyInfo.DeclaringType, DeclaringType))
{
MarkNameWithTypeName();
}
}
private static bool IsSubTypeOf(Type possibleSubType, Type possibleBaseType)
{
return possibleSubType.IsSubclassOf(possibleBaseType);
}
}
}
namespace Serilog.Exceptions.Filters
{
public class CompositeExceptionPropertyFilter : IExceptionPropertyFilter
{
private readonly IExceptionPropertyFilter[] filters;
public CompositeExceptionPropertyFilter(params IExceptionPropertyFilter[] filters)
{
if (filters == null)
{
throw new ArgumentNullException("filters");
}
if (filters.Length == 0)
{
throw new ArgumentException(Resources.CannotBeEmpty, "filters");
}
for (int i = 0; i < filters.Length; i++)
{
if (filters[i] == null)
{
throw new ArgumentException($"Cannot create composite exception properties filter, because filter at index {i} is null", "filters");
}
}
this.filters = filters;
}
public bool ShouldPropertyBeFiltered(Exception exception, string propertyName, object? value)
{
for (int i = 0; i < filters.Length; i++)
{
if (filters[i].ShouldPropertyBeFiltered(exception, propertyName, value))
{
return true;
}
}
return false;
}
}
public interface IExceptionPropertyFilter
{
bool ShouldPropertyBeFiltered(Exception exception, string propertyName, object? value);
}
public class IgnorePropertyByNameExceptionFilter : IExceptionPropertyFilter
{
private readonly string[] propertiesToIgnore;
public IgnorePropertyByNameExceptionFilter(params string[] propertiesToIgnore)
{
this.propertiesToIgnore = propertiesToIgnore;
}
public bool ShouldPropertyBeFiltered(Exception exception, string propertyName, object? value)
{
if (propertiesToIgnore == null)
{
return false;
}
for (int i = 0; i < propertiesToIgnore.Length; i++)
{
if (propertiesToIgnore[i].Equals(propertyName, StringComparison.Ordinal))
{
return true;
}
}
return false;
}
}
}
namespace Serilog.Exceptions.Destructurers
{
public class AggregateExceptionDestructurer : ExceptionDestructurer
{
public override Type[] TargetTypes => new Type[1] { typeof(AggregateException) };
public override void Destructure(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException)
{
base.Destructure(exception, propertiesBag, destructureException);
AggregateException ex = (AggregateException)exception;
propertiesBag.AddProperty("InnerExceptions", ex.InnerExceptions.Select(destructureException).ToList());
}
}
public class ArgumentExceptionDestructurer : ExceptionDestructurer
{
public override Type[] TargetTypes => new Type[2]
{
typeof(ArgumentException),
typeof(ArgumentNullException)
};
public override void Destructure(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException)
{
base.Destructure(exception, propertiesBag, destructureException);
ArgumentException ex = (ArgumentException)exception;
propertiesBag.AddProperty("ParamName", ex.ParamName);
}
}
public class ArgumentOutOfRangeExceptionDestructurer : ArgumentExceptionDestructurer
{
public override Type[] TargetTypes => new Type[1] { typeof(ArgumentOutOfRangeException) };
public override void Destructure(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException)
{
base.Destructure(exception, propertiesBag, destructureException);
ArgumentOutOfRangeException ex = (ArgumentOutOfRangeException)exception;
propertiesBag.AddProperty("ActualValue", ex.ActualValue);
}
}
public class ExceptionDestructurer : IExceptionDestructurer
{
public virtual Type[] TargetTypes => new List<Type>
{
typeof(AccessViolationException),
typeof(AppDomainUnloadedException),
typeof(ApplicationException),
typeof(ArithmeticException),
typeof(ArrayTypeMismatchException),
typeof(CannotUnloadAppDomainException),
typeof(KeyNotFoundException),
typeof(CheckoutException),
typeof(InvalidAsynchronousStateException),
typeof(InvalidEnumArgumentException),
typeof(ContextMarshalException),
typeof(ConstraintException),
typeof(DataException),
typeof(DeletedRowInaccessibleException),
typeof(DuplicateNameException),
typeof(EvaluateException),
typeof(InRowChangingEventException),
typeof(InvalidConstraintException),
typeof(InvalidExpressionException),
typeof(MissingPrimaryKeyException),
typeof(NoNullAllowedException),
typeof(ReadOnlyException),
typeof(RowNotInTableException),
typeof(SqlAlreadyFilledException),
typeof(SqlNotFilledException),
typeof(StrongTypingException),
typeof(SyntaxErrorException),
typeof(VersionNotFoundException),
typeof(EventSourceException),
typeof(DataMisalignedException),
typeof(DivideByZeroException),
typeof(DllNotFoundException),
typeof(DuplicateWaitObjectException),
typeof(EntryPointNotFoundException),
typeof(Exception),
typeof(FieldAccessException),
typeof(FormatException),
typeof(IndexOutOfRangeException),
typeof(InsufficientExecutionStackException),
typeof(InsufficientMemoryException),
typeof(InvalidCastException),
typeof(InvalidOperationException),
typeof(InvalidProgramException),
typeof(InvalidTimeZoneException),
typeof(DirectoryNotFoundException),
typeof(DriveNotFoundException),
typeof(EndOfStreamException),
typeof(InternalBufferOverflowException),
typeof(InvalidDataException),
typeof(IOException),
typeof(IsolatedStorageException),
typeof(PathTooLongException),
typeof(MemberAccessException),
typeof(MethodAccessException),
typeof(MulticastNotSupportedException),
typeof(CookieException),
typeof(PingException),
typeof(ProtocolViolationException),
typeof(NotImplementedException),
typeof(NotSupportedException),
typeof(NullReferenceException),
typeof(OutOfMemoryException),
typeof(OverflowException),
typeof(PlatformNotSupportedException),
typeof(RankException),
typeof(AmbiguousMatchException),
typeof(CustomAttributeFormatException),
typeof(InvalidFilterCriteriaException),
typeof(TargetException),
typeof(TargetInvocationException),
typeof(TargetParameterCountException),
typeof(MissingManifestResourceException),
typeof(AmbiguousImplementationException),
typeof(COMException),
typeof(InvalidComObjectException),
typeof(InvalidOleVariantTypeException),
typeof(MarshalDirectiveException),
typeof(SafeArrayRankMismatchException),
typeof(SafeArrayTypeMismatchException),
typeof(SEHException),
typeof(SerializationException),
typeof(AuthenticationException),
typeof(InvalidCredentialException),
typeof(CryptographicException),
typeof(CryptographicUnexpectedOperationException),
typeof(VerificationException),
typeof(StackOverflowException),
typeof(SystemException),
typeof(BarrierPostPhaseException),
typeof(LockRecursionException),
typeof(SemaphoreFullException),
typeof(SynchronizationLockException),
typeof(TaskSchedulerException),
typeof(ThreadInterruptedException),
typeof(ThreadStartException),
typeof(ThreadStateException),
typeof(WaitHandleCannotBeOpenedException),
typeof(TimeoutException),
typeof(TimeZoneNotFoundException),
typeof(TypeAccessException),
typeof(TypeUnloadedException),
typeof(UnauthorizedAccessException),
typeof(UriFormatException)
}.ToArray();
public virtual void Destructure(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException)
{
if (exception == null)
{
throw new ArgumentNullException("exception");
}
if (propertiesBag == null)
{
throw new ArgumentNullException("propertiesBag");
}
if (destructureException == null)
{
throw new ArgumentNullException("destructureException");
}
propertiesBag.AddProperty("Type", exception.GetType().FullName);
DestructureCommonExceptionProperties(exception, propertiesBag, destructureException, (IDictionary data) => data.ToStringObjectDictionary());
}
internal static void DestructureCommonExceptionProperties(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> innerDestructure, Func<IDictionary, object> destructureDataProperty)
{
if (exception.Data.Count != 0)
{
propertiesBag.AddProperty("Data", destructureDataProperty(exception.Data));
}
if (!string.IsNullOrEmpty(exception.HelpLink))
{
propertiesBag.AddProperty("HelpLink", exception.HelpLink);
}
if (exception.HResult != 0)
{
propertiesBag.AddProperty("HResult", exception.HResult);
}
propertiesBag.AddProperty("Message", exception.Message);
propertiesBag.AddProperty("Source", exception.Source);
propertiesBag.AddProperty("StackTrace", exception.StackTrace);
if ((object)exception.TargetSite != null)
{
propertiesBag.AddProperty("TargetSite", exception.TargetSite.ToString());
}
if (exception.InnerException != null)
{
propertiesBag.AddProperty("InnerException", innerDestructure(exception.InnerException));
}
}
}
public interface IExceptionDestructurer
{
Type[] TargetTypes { get; }
void Destructure(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException);
}
public class OperationCanceledExceptionDestructurer : ExceptionDestructurer
{
private const string CancellationTokenTrue = "CancellationRequested: true";
private const string CancellationTokenFalse = "CancellationRequested: false";
private static readonly Type[] TargetExceptionTypes = new Type[1] { typeof(OperationCanceledException) };
public override Type[] TargetTypes => TargetExceptionTypes;
public override void Destructure(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException)
{
base.Destructure(exception, propertiesBag, destructureException);
OperationCanceledException ex = (OperationCanceledException)exception;
CancellationToken cancellationToken = ex.CancellationToken;
propertiesBag.AddProperty("CancellationToken", DestructureCancellationToken(in cancellationToken));
}
internal static object DestructureCancellationToken(in CancellationToken cancellationToken)
{
if (!cancellationToken.IsCancellationRequested)
{
return "CancellationRequested: false";
}
return "CancellationRequested: true";
}
}
public class ReflectionBasedDestructurer : IExceptionDestructurer
{
private const string IdLabel = "$id";
private const string RefLabel = "$ref";
private const string CyclicReferenceMessage = "Cyclic reference";
private const string IQueryableDestructureSkippedMessage = "IQueryable skipped";
private readonly int destructuringDepth;
private readonly ReflectionInfoExtractor reflectionInfoExtractor = new ReflectionInfoExtractor();
public Type[] TargetTypes => new Type[1] { typeof(Exception) };
public ReflectionBasedDestructurer(int destructuringDepth)
{
if (destructuringDepth <= 0)
{
throw new ArgumentOutOfRangeException("destructuringDepth", destructuringDepth, Resources.DestructuringDepthMustBeMoreThanZero);
}
this.destructuringDepth = destructuringDepth;
}
public void Destructure(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException)
{
if (exception == null)
{
throw new ArgumentNullException("exception");
}
if (propertiesBag == null)
{
throw new ArgumentNullException("propertiesBag");
}
if (destructureException == null)
{
throw new ArgumentNullException("destructureException");
}
int nextCyclicRefId = 1;
Dictionary<object, IDictionary<string, object?>> destructuredObjects = new Dictionary<object, IDictionary<string, object>>();
ExceptionDestructurer.DestructureCommonExceptionProperties(exception, propertiesBag, destructureException, (IDictionary data) => DestructureValueDictionary(data, 1, destructuredObjects, ref nextCyclicRefId));
ReflectionInfo orCreateReflectionInfo = reflectionInfoExtractor.GetOrCreateReflectionInfo(exception.GetType());
AppendProperties(exception, orCreateReflectionInfo.PropertiesExceptBaseOnes, propertiesBag.AddProperty, destructuredObjects, 0, ref nextCyclicRefId);
AppendTypeIfPossible(propertiesBag, exception.GetType());
}
private static string? GetOrGenerateRefId(ref int nextCyclicRefId, IDictionary<string, object?> destructuredObject)
{
string result;
if (destructuredObject.TryGetValue("$id", out object value))
{
result = (string)value;
}
else
{
int num = nextCyclicRefId;
nextCyclicRefId++;
result = (string)(destructuredObject["$id"] = num.ToString(CultureInfo.InvariantCulture));
}
return result;
}
private static object DestructureUri(Uri value)
{
return value.ToString();
}
private static void AppendTypeIfPossible(IExceptionPropertiesBag propertiesBag, Type valueType)
{
if (propertiesBag.ContainsProperty("Type"))
{
if (!propertiesBag.ContainsProperty("$Type"))
{
propertiesBag.AddProperty("$Type", valueType.FullName);
}
}
else
{
propertiesBag.AddProperty("Type", valueType.FullName);
}
}
private void AppendProperties(object value, ReflectionPropertyInfo[] reflectionPropertyInfos, Action<string, object?> addPropertyAction, IDictionary<object, IDictionary<string, object?>> destructuredObjects, int level, ref int nextCyclicRefId)
{
foreach (ReflectionPropertyInfo reflectionPropertyInfo in reflectionPropertyInfos)
{
try
{
object value2 = reflectionPropertyInfo.Getter(value);
int nextCyclicRefId2 = nextCyclicRefId;
object arg = DestructureValue(value2, level + 1, destructuredObjects, ref nextCyclicRefId2);
nextCyclicRefId = nextCyclicRefId2;
addPropertyAction(reflectionPropertyInfo.Name, arg);
}
catch (TargetInvocationException ex)
{
Exception innerException = ex.InnerException;
if (innerException != null)
{
addPropertyAction(reflectionPropertyInfo.Name, "threw " + innerException.GetType().FullName + ": " + innerException.Message);
}
}
catch (Exception ex2)
{
addPropertyAction(reflectionPropertyInfo.Name, "threw " + ex2.GetType().FullName + ": " + ex2.Message);
}
}
}
private object? DestructureValue(object? value, int level, IDictionary<object, IDictionary<string, object?>> destructuredObjects, ref int nextCyclicRefId)
{
if (value == null)
{
return null;
}
Type type = value.GetType();
TypeInfo typeInfo = type.GetTypeInfo();
if (value is MemberInfo)
{
return value;
}
if (type.GetTypeCode() != TypeCode.Object || typeInfo.IsValueType)
{
return value;
}
if (level > destructuringDepth)
{
return value;
}
if (value is IDictionary value2)
{
return DestructureValueDictionary(value2, level, destructuredObjects, ref nextCyclicRefId);
}
if (value is IQueryable)
{
return "IQueryable skipped";
}
if (value is IEnumerable value3)
{
return DestructureValueEnumerable(value3, level, destructuredObjects, ref nextCyclicRefId);
}
if (value is Uri value4)
{
return DestructureUri(value4);
}
if (value is CancellationToken cancellationToken)
{
return OperationCanceledExceptionDestructurer.DestructureCancellationToken(in cancellationToken);
}
if (value is Task task)
{
return DestructureTask(task, level, destructuredObjects, ref nextCyclicRefId);
}
return DestructureObject(value, type, level, destructuredObjects, ref nextCyclicRefId);
}
private object DestructureValueEnumerable(IEnumerable value, int level, IDictionary<object, IDictionary<string, object?>> destructuredObjects, ref int nextCyclicRefId)
{
if (destructuredObjects.ContainsKey(value))
{
return new Dictionary<string, object> { { "$ref", "Cyclic reference" } };
}
destructuredObjects.Add(value, new Dictionary<string, object>());
List<object> list = new List<object>();
foreach (object item in value.Cast<object>())
{
list.Add(DestructureValue(item, level + 1, destructuredObjects, ref nextCyclicRefId));
}
return list;
}
private object DestructureValueDictionary(IDictionary value, int level, IDictionary<object, IDictionary<string, object?>> destructuredObjects, ref int nextCyclicRefId)
{
if (destructuredObjects.TryGetValue(value, out IDictionary<string, object> value2))
{
string orGenerateRefId = GetOrGenerateRefId(ref nextCyclicRefId, value2);
return new Dictionary<string, object> { { "$ref", orGenerateRefId } };
}
Dictionary<string, object> dictionary = value.ToStringObjectDictionary();
destructuredObjects.Add(value, dictionary);
foreach (KeyValuePair<string, object> item in dictionary.ToDictionary((KeyValuePair<string, object> k) => k.Key, (KeyValuePair<string, object> v) => v.Value))
{
dictionary[item.Key] = DestructureValue(item.Value, level + 1, destructuredObjects, ref nextCyclicRefId);
}
return dictionary;
}
private IDictionary<string, object?> DestructureObject(object value, Type valueType, int level, IDictionary<object, IDictionary<string, object?>> destructuredObjects, ref int nextCyclicRefId)
{
if (destructuredObjects.TryGetValue(value, out IDictionary<string, object> value2))
{
string orGenerateRefId = GetOrGenerateRefId(ref nextCyclicRefId, value2);
return new Dictionary<string, object> { { "$ref", orGenerateRefId } };
}
Dictionary<string, object> dictionary = new Dictionary<string, object>();
destructuredObjects.Add(value, dictionary);
ReflectionPropertyInfo[] properties = reflectionInfoExtractor.GetOrCreateReflectionInfo(valueType).Properties;
foreach (ReflectionPropertyInfo reflectionPropertyInfo in properties)
{
try
{
object value3 = reflectionPropertyInfo.Getter(value);
object value4 = DestructureValue(value3, level + 1, destructuredObjects, ref nextCyclicRefId);
dictionary.Add(reflectionPropertyInfo.Name, value4);
}
catch (TargetInvocationException ex)
{
Exception innerException = ex.InnerException;
if (innerException != null)
{
dictionary.Add(reflectionPropertyInfo.Name, "threw " + innerException.GetType().FullName + ": " + innerException.Message);
}
}
catch (Exception ex2)
{
dictionary.Add(reflectionPropertyInfo.Name, "threw " + ex2.GetType().FullName + ": " + ex2.Message);
}
}
return dictionary;
}
private object DestructureTask(Task task, int level, IDictionary<object, IDictionary<string, object?>> destructuredObjects, ref int nextCyclicRefId)
{
if (destructuredObjects.TryGetValue(task, out IDictionary<string, object> value))
{
string orGenerateRefId = GetOrGenerateRefId(ref nextCyclicRefId, value);
return new SortedList<string, object> { { "$ref", orGenerateRefId } };
}
SortedList<string, object> sortedList = new SortedList<string, object>();
destructuredObjects.Add(task, sortedList);
sortedList["Id"] = task.Id;
sortedList["Status"] = task.Status.ToString("G");
sortedList["CreationOptions"] = task.CreationOptions.ToString("F");
if (task.IsFaulted)
{
sortedList["Exception"] = DestructureValue(task.Exception, level, destructuredObjects, ref nextCyclicRefId);
}
return sortedList;
}
}
public class ReflectionTypeLoadExceptionDestructurer : ExceptionDestructurer
{
public override Type[] TargetTypes => new Type[1] { typeof(ReflectionTypeLoadException) };
public override void Destructure(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException)
{
base.Destructure(exception, propertiesBag, destructureException);
ReflectionTypeLoadException ex = (ReflectionTypeLoadException)exception;
if (ex.LoaderExceptions != null)
{
propertiesBag.AddProperty("LoaderExceptions", GetLoaderExceptionsValue(ex.LoaderExceptions, destructureException));
}
}
private static List<IReadOnlyDictionary<string, object?>> GetLoaderExceptionsValue(Exception?[] exceptions, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException)
{
List<IReadOnlyDictionary<string, object>> list = new List<IReadOnlyDictionary<string, object>>();
foreach (Exception ex in exceptions)
{
if (ex != null)
{
IReadOnlyDictionary<string, object> readOnlyDictionary = destructureException(ex);
if (readOnlyDictionary != null)
{
list.Add(readOnlyDictionary);
}
}
}
return list;
}
}
public class RegexMatchTimeoutExceptionDestructurer : ExceptionDestructurer
{
public override Type[] TargetTypes => new Type[1] { typeof(RegexMatchTimeoutException) };
public override void Destructure(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException)
{
base.Destructure(exception, propertiesBag, destructureException);
RegexMatchTimeoutException ex = (RegexMatchTimeoutException)exception;
propertiesBag.AddProperty("Input", ex.Input);
propertiesBag.AddProperty("Pattern", ex.Pattern);
propertiesBag.AddProperty("MatchTimeout", ex.MatchTimeout.ToString("c"));
}
}
public class SocketExceptionDestructurer : ExceptionDestructurer
{
private static readonly IReadOnlyDictionary<SocketError, string> SocketErrorDocumentationBySocketError = new Dictionary<SocketError, string>
{
{
SocketError.AccessDenied,
"An attempt was made to access a Socket in a way that is forbidden by its access permissions."
},
{
SocketError.AddressAlreadyInUse,
"Only one use of an address is normally permitted."
},
{
SocketError.AddressFamilyNotSupported,
"The address family specified is not supported. This error is returned if the IPv6 address family was specified and the IPv6 stack is not installed on the local machine. This error is returned if the IPv4 address family was specified and the IPv4 stack is not installed on the local machine."
},
{
SocketError.AddressNotAvailable,
"The selected IP address is not valid in this context."
},
{
SocketError.AlreadyInProgress,
"The nonblocking Socket already has an operation in progress."
},
{
SocketError.ConnectionAborted,
"The connection was aborted by the .NET Framework or the underlying socket provider."
},
{
SocketError.ConnectionRefused,
"The remote host is actively refusing a connection."
},
{
SocketError.ConnectionReset,
"The connection was reset by the remote peer."
},
{
SocketError.DestinationAddressRequired,
"A required address was omitted from an operation on a Socket."
},
{
SocketError.Disconnecting,
"A graceful shutdown is in progress."
},
{
SocketError.Fault,
"An invalid pointer address was detected by the underlying socket provider."
},
{
SocketError.HostDown,
"The operation failed because the remote host is down."
},
{
SocketError.HostNotFound,
"No such host is known. The name is not an official host name or alias."
},
{
SocketError.HostUnreachable,
"There is no network route to the specified host."
},
{
SocketError.InProgress,
"A blocking operation is in progress."
},
{
SocketError.Interrupted,
"A blocking Socket call was canceled."
},
{
SocketError.InvalidArgument,
"An invalid argument was supplied to a Socket member."
},
{
SocketError.IOPending,
"The application has initiated an overlapped operation that cannot be completed immediately."
},
{
SocketError.IsConnected,
"The Socket is already connected."
},
{
SocketError.MessageSize,
"The datagram is too long."
},
{
SocketError.NetworkDown,
"The network is not available."
},
{
SocketError.NetworkReset,
"The application tried to set KeepAlive on a connection that has already timed out."
},
{
SocketError.NetworkUnreachable,
"No route to the remote host exists."
},
{
SocketError.NoBufferSpaceAvailable,
"No free buffer space is available for a Socket operation."
},
{
SocketError.NoData,
"The requested name or IP address was not found on the name server."
},
{
SocketError.NoRecovery,
"The error is unrecoverable or the requested database cannot be located."
},
{
SocketError.NotConnected,
"The application tried to send or receive data, and the Socket is not connected."
},
{
SocketError.NotInitialized,
"The underlying socket provider has not been initialized."
},
{
SocketError.NotSocket,
"A Socket operation was attempted on a non-socket."
},
{
SocketError.OperationAborted,
"The overlapped operation was aborted due to the closure of the Socket."
},
{
SocketError.OperationNotSupported,
"The address family is not supported by the protocol family."
},
{
SocketError.ProcessLimit,
"Too many processes are using the underlying socket provider."
},
{
SocketError.ProtocolFamilyNotSupported,
"The protocol family is not implemented or has not been configured."
},
{
SocketError.ProtocolNotSupported,
"The protocol is not implemented or has not been configured."
},
{
SocketError.ProtocolOption,
"An unknown, invalid, or unsupported option or level was used with a Socket."
},
{
SocketError.ProtocolType,
"The protocol type is incorrect for this Socket."
},
{
SocketError.Shutdown,
"A request to send or receive data was disallowed because the Socket has already been closed."
},
{
SocketError.SocketError,
"An unspecified Socket error has occurred."
},
{
SocketError.SocketNotSupported,
"The support for the specified socket type does not exist in this address family."
},
{
SocketError.Success,
"The Socket operation succeeded."
},
{
SocketError.SystemNotReady,
"The network subsystem is unavailable."
},
{
SocketError.TimedOut,
"The connection attempt timed out, or the connected host has failed to respond."
},
{
SocketError.TooManyOpenSockets,
"There are too many open sockets in the underlying socket provider."
},
{
SocketError.TryAgain,
"The name of the host could not be resolved. Try again later."
},
{
SocketError.TypeNotFound,
"The specified class was not found."
},
{
SocketError.VersionNotSupported,
"The version of the underlying socket provider is out of range."
},
{
SocketError.WouldBlock,
"An operation on a nonblocking socket cannot be completed immediately."
}
};
public override Type[] TargetTypes => new Type[1] { typeof(SocketException) };
public override void Destructure(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException)
{
base.Destructure(exception, propertiesBag, destructureException);
SocketException ex = (SocketException)exception;
propertiesBag.AddProperty("SocketErrorCode", ex.SocketErrorCode);
if (SocketErrorDocumentationBySocketError.TryGetValue(ex.SocketErrorCode, out string value))
{
propertiesBag.AddProperty("SocketErrorCodeMessage", value);
}
}
}
public class TaskCanceledExceptionDestructurer : OperationCanceledExceptionDestructurer
{
private static readonly Type[] TargetExceptionTypes = new Type[1] { typeof(TaskCanceledException) };
public override Type[] TargetTypes => TargetExceptionTypes;
public override void Destructure(Exception exception, IExceptionPropertiesBag propertiesBag, Func<Exception, IReadOnlyDictionary<string, object?>?> destructureException)
{
base.Destructure(exception, propertiesBag, destructureException);
TaskCanceledException ex = (TaskCanceledException)exception;
propertiesBag.AddProperty("Task", DestructureTask(ex.Task, destructureException));
}
internal static object? DestructureTask(Task? task, Func<Exception, IReadOnlyDictionary<string, object?>?> innerDestructure)
{
if (task == null)
{
return null;
}
string status = task.Status.ToString("G");
string creationOptions = task.CreationOptions.ToString("F");
if (task.IsFaulted && task.Exception != null)
{
return new
{
Id = task.Id,
Status = status,
CreationOptions = creationOptions,
Exception = innerDestructure(task.Exception)
};
}
return new
{
Id = task.Id,
Status = status,
CreationOptions = creationOptions
};
}
}
}
namespace Serilog.Exceptions.Core
{
public class DestructuringOptionsBuilder : IDestructuringOptions
{
public static readonly IExceptionDestructurer[] DefaultDestructurers = new IExceptionDestructurer[9]
{
new ExceptionDestructurer(),
new ArgumentExceptionDestructurer(),
new ArgumentOutOfRangeExceptionDestructurer(),
new AggregateExceptionDestructurer(),
new RegexMatchTimeoutExceptionDestructurer(),
new ReflectionTypeLoadExceptionDestructurer(),
new OperationCanceledExceptionDestructurer(),
new TaskCanceledExceptionDestructurer(),
new SocketExceptionDestructurer()
};
public static readonly IExceptionPropertyFilter IgnoreStackTraceAndTargetSiteExceptionFilter = new IgnorePropertyByNameExceptionFilter("StackTrace");
private readonly List<IExceptionDestructurer> destructurers = new List<IExceptionDestructurer>();
public string RootName { get; private set; } = "ExceptionDetail";
public int DestructuringDepth { get; private set; } = 10;
public bool DisableReflectionBasedDestructurer { get; private set; }
public IEnumerable<IExceptionDestructurer> Destructurers => destructurers;
public IExceptionPropertyFilter? Filter { get; private set; }
public DestructuringOptionsBuilder WithDestructurers(IEnumerable<IExceptionDestructurer> destructurers)
{
if (destructurers == null)
{
throw new ArgumentNullException("destructurers");
}
this.destructurers.AddRange(destructurers);
return this;
}
public DestructuringOptionsBuilder WithDefaultDestructurers()
{
return WithDestructurers(DefaultDestructurers);
}
public DestructuringOptionsBuilder WithFilter(IExceptionPropertyFilter filter)
{
if (Filter != null)
{
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Resources.FilterAlreadySet, "CompositeExceptionPropertyFilter"));
}
Filter = filter;
return this;
}
public DestructuringOptionsBuilder WithIgnoreStackTraceAndTargetSiteExceptionFilter()
{
return WithFilter(IgnoreStackTraceAndTargetSiteExceptionFilter);
}
public DestructuringOptionsBuilder WithRootName(string rootName)
{
if (rootName == null)
{
throw new ArgumentNullException("rootName");
}
if (rootName.Length == 0)
{
throw new ArgumentException(Resources.CannotBeEmpty, "rootName");
}
RootName = rootName;
return this;
}
public DestructuringOptionsBuilder WithDestructuringDepth(int destructuringDepth)
{
if (destructuringDepth <= 0)
{
throw new ArgumentOutOfRangeException("destructuringDepth", destructuringDepth, Resources.DestructuringDepthMustBeMoreThanZero);
}
DestructuringDepth = destructuringDepth;
return this;
}
public DestructuringOptionsBuilder WithoutReflectionBasedDestructurer()
{
DisableReflectionBasedDestructurer = true;
return this;
}
}
public sealed class ExceptionEnricher : ILogEventEnricher
{
private readonly IExceptionDestructurer reflectionBasedDestructurer;
private readonly Dictionary<Type, IExceptionDestructurer> destructurers;
private readonly IDestructuringOptions destructuringOptions;
public ExceptionEnricher()
: this(new DestructuringOptionsBuilder().WithDefaultDestructurers())
{
}
public ExceptionEnricher(IDestructuringOptions destructuringOptions)
{
this.destructuringOptions = destructuringOptions ?? throw new ArgumentNullException("destructuringOptions");
reflectionBasedDestructurer = new ReflectionBasedDestructurer(destructuringOptions.DestructuringDepth);
destructurers = new Dictionary<Type, IExceptionDestructurer>();
foreach (IExceptionDestructurer destructurer in this.destructuringOptions.Destructurers)
{
Type[] targetTypes = destructurer.TargetTypes;
foreach (Type key in targetTypes)
{
destructurers.Add(key, destructurer);
}
}
}
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
if (logEvent == null)
{
throw new ArgumentNullException("logEvent");
}
if (propertyFactory == null)
{
throw new ArgumentNullException("propertyFactory");
}
if (logEvent.Exception != null)
{
IReadOnlyDictionary<string, object> readOnlyDictionary = DestructureException(logEvent.Exception);
if (readOnlyDictionary != null)
{
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty(destructuringOptions.RootName, (object)readOnlyDictionary, true));
}
}
}
private IReadOnlyDictionary<string, object?>? DestructureException(Exception exception)
{
Type type = exception.GetType();
if (destructurers.TryGetValue(type, out IExceptionDestructurer value))
{
ExceptionPropertiesBag exceptionPropertiesBag = new ExceptionPropertiesBag(exception, destructuringOptions.Filter);
value.Destructure(exception, exceptionPropertiesBag, DestructureException);
return exceptionPropertiesBag.GetResultDictionary();
}
if (!destructuringOptions.DisableReflectionBasedDestructurer)
{
ExceptionPropertiesBag exceptionPropertiesBag2 = new ExceptionPropertiesBag(exception, destructuringOptions.Filter);
reflectionBasedDestructurer.Destructure(exception, exceptionPropertiesBag2, DestructureException);
return exceptionPropertiesBag2.GetResultDictionary();
}
return null;
}
}
internal class ExceptionPropertiesBag : IExceptionPropertiesBag
{
private const int AcceptableNumberOfSameNameProperties = 5;
private readonly Exception exception;
private readonly IExceptionPropertyFilter? filter;
private readonly Dictionary<string, object?> properties = new Dictionary<string, object>();
private bool resultsCollected;
public ExceptionPropertiesBag(Exception exception, IExceptionPropertyFilter? filter = null)
{
this.exception = exception ?? throw new ArgumentNullException("exception");
this.filter = filter;
}
public IReadOnlyDictionary<string, object?> GetResultDictionary()
{
resultsCollected = true;
return properties;
}
public void AddProperty(string key, object? value)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
if (resultsCollected)
{
throw new InvalidOperationException("Cannot add exception property '" + key + "' to bag, after results were already collected");
}
if (filter == null || !filter.ShouldPropertyBeFiltered(exception, key, value))
{
AddPairToProperties(key, value);
}
}
public bool ContainsProperty(string key)
{
return properties.ContainsKey(key);
}
private static string GetReplacementKey(string key)
{
return key + "$";
}
private void AddPairToProperties(string key, object? value)
{
key = MakeSureKeyIsUnique(key);
properties.Add(key, value);
}
private string MakeSureKeyIsUnique(string key)
{
int num = 0;
while (properties.ContainsKey(key) && num < 5)
{
key = GetReplacementKey(key);
num++;
}
return key;
}
}
public interface IDestructuringOptions
{
string RootName { get; }
int DestructuringDepth { get; }
IEnumerable<IExceptionDestructurer> Destructurers { get; }
IExceptionPropertyFilter? Filter { get; }
bool DisableReflectionBasedDestructurer { get; }
}
public interface IExceptionPropertiesBag
{
IReadOnlyDictionary<string, object?> GetResultDictionary();
void AddProperty(string key, object? value);
bool ContainsProperty(string key);
}
}