GithubHelp home page GithubHelp logo

benaadams / ben.demystifier Goto Github PK

View Code? Open in Web Editor NEW
2.8K 74.0 118.0 426 KB

High performance understanding for stack traces (Make error logs more productive)

License: Apache License 2.0

C# 99.24% PowerShell 0.76%
stack-traces aspnet-core dotnet dotnet-core error-handling error-messages exceptions

ben.demystifier's Introduction

Ben.Demystifier

NuGet version (Ben.Demystifier) build

Output the modern C# 7.0+ features in stack traces that looks like the C# source code that generated them rather than IL formatted.

High performance understanding for stack traces

.NET stack traces output the compiler transformed methods; rather than the source code methods, which make them slow to mentally parse and match back to the source code.

The current output was good for C# 1.0; but has become progressively worse since C# 2.0 (iterators, generics) as new features are added to the .NET languages and at C# 7.1 the stack traces are esoteric (see: Problems with current stack traces).

Make error logs more productive

Output the modern C# 7.0+ features in stack traces in an understandable fashion that looks like the C# source code that generated them.

Demystified stacktrace

Usage

exception.Demystify()

Or instead of Environment.StackTrace

EnhancedStackTrace.Current()

Resolves the stack back to the C# source format of the calls (and is an inspectable list of stack frames)

Calling .ToString() on the Demystified exception will produce a string stacktrace similar to the following (without the comments):

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at bool System.Collections.Generic.List<T>+Enumerator.MoveNextRare()
   at IEnumerable<string> Program.Iterator(int startAt)+MoveNext()                       // Resolved enumerator
   at bool System.Linq.Enumerable+SelectEnumerableIterator<TSource, TResult>.MoveNext()  // Resolved enumerator
   at string string.Join(string separator, IEnumerable<string> values)                    
   at string Program+GenericClass<TSuperType>.GenericMethod<TSubType>(ref TSubType value) 
   at async Task<string> Program.MethodAsync(int value)                                  // Resolved async 
   at async Task<string> Program.MethodAsync<TValue>(TValue value)                       // Resolved async 
   at string Program.Method(string value)+()=>{} [0]                                     // lambda source + ordinal
   at string Program.Method(string value)+()=>{} [1]                                     // lambda source + ordinal 
   at string Program.RunLambda(Func<string> lambda)                                       
   at (string val, bool) Program.Method(string value)                                    // Tuple returning
   at ref string Program.RefMethod(in string value)+LocalFuncRefReturn()                 // ref return local func
   at int Program.RefMethod(in string value)+LocalFuncParam(string val)                  // local function
   at string Program.RefMethod(in string value)                                          // in param (readonly ref)    
   at (string val, bool) static Program()+(string s, bool b)=>{}                         // tuple return static lambda
   at void static Program()+(string s, bool b)=>{}                                       // void static lambda
   at void Program.Start((string val, bool) param)                                       // Resolved tuple param
   at void Program.Start((string val, bool) param)+LocalFunc1(long l)                    // void local function 
   at bool Program.Start((string val, bool) param)+LocalFunc2(bool b1, bool b2)          // bool return local function 
   at string Program.Start()                                                              
   at void Program()+()=>{}                                                              // ctor defined lambda  
   at void Program(Action action)+(object state)=>{}                                     // ctor defined lambda 
   at void Program.RunAction(Action<object> lambda, object state)                         
   at new Program(Action action)                                                         // constructor 
   at new Program()                                                                      // constructor 
   at void Program.Main(String[] args)                                                    

Calling .ToString() on the same exception would produce the following output

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion() // ? low value
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()                         
   at Program.<Iterator>d__3.MoveNext()                                                   // which enumerator?
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()                        // which enumerator?
   at System.String.Join(String separator, IEnumerable`1 values)                          
   at Program.GenericClass`1.GenericMethod[TSubType](TSubType& value)                     
   at Program.<MethodAsync>d__4.MoveNext()                                                // which async overload?
--- End of stack trace from previous location where exception was thrown ---              // ? no value
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()                      // ? no value
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) // ? no value
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()                           // ? no value
   at Program.<MethodAsync>d__5`1.MoveNext()                                              // which async overload?
--- End of stack trace from previous location where exception was thrown ---              // ? no value
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()                      // ? no value
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) // ? no value
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()                           // ? no value
   at Program.<>c__DisplayClass8_0.<Method>b__0()                                         //  ¯\_(ツ)_/¯
   at Program.<>c__DisplayClass8_0.<Method>b__1()                                         //  ¯\_(ツ)_/¯
   at Program.RunLambda(Func`1 lambda) 
   at Program.Method(String value)
   at Program.<RefMethod>g__LocalFuncRefReturn|10_1(<>c__DisplayClass10_0& )              // local function
   at Program.<RefMethod>g__LocalFuncParam|10_0(String val, <>c__DisplayClass10_0& )      // local function
   at Program.RefMethod(String value)
   at Program.<>c.<.cctor>b__18_1(String s, Boolean b)                                    //  ¯\_(ツ)_/¯
   at Program.<>c.<.cctor>b__18_0(String s, Boolean b)                                    //  ¯\_(ツ)_/¯
   at Program.Start(ValueTuple`2 param)                                                   // Tuple param?
   at Program.<Start>g__LocalFunc1|11_0(Int64 l)                                          // local function
   at Program.<Start>g__LocalFunc2|11_1(Boolean b1, Boolean b2)                           // local function
   at Program.Start()
   at Program.<>c.<.ctor>b__1_0()                                                         //  ¯\_(ツ)_/¯
   at Program.<>c__DisplayClass2_0.<.ctor>b__0(Object state)                              //  ¯\_(ツ)_/¯
   at Program.RunAction(Action`1 lambda, Object state)
   at Program..ctor(Action action)                                                        // constructor
   at Program..ctor()                                                                     // constructor
   at Program.Main(String[] args)

Which is far less helpful, and close to jibberish in places

Problems with current stack traces:

  • constructors

    Does not match code, output as .ctor and .cctor

  • parameters

    Do not specify qualifier ref, out or in

  • iterators

    Cannot determine overload <Iterator>d__3.MoveNext() rather than Iterator(int startAt)+MoveNext()

  • Linq

    Cannot determine overload

    Linq.Enumerable.SelectEnumerableIterator``2.MoveNext()

    rather than

    Linq.Enumerable+SelectEnumerableIterator<TSource, TResult>.MoveNext()

  • async

    Cannot determine overload and no modifier such as async

    <MethodAsync>d__5``1.MoveNext()

    rather than

    async Task<string> Program.MethodAsync(int value)

    Noise!

    --- End of stack trace from previous location where exception was thrown ---
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.GetResult() 
    
  • lambdas

    Mostly jibberish <>c__DisplayClass2_0.<.ctor>b__0(Object state) with a suggestion of where they are declared but no hint if there are multiple overloads of the method.

  • local functions

    Mostly jibberish <RefMethod>g__LocalFuncParam|10_0(String val, <>c__DisplayClass10_0& ) with a suggestion of where they are declared but no hint if there are multiple overloads of the method.

  • generic parameters

    Not resolved, only an indication of the number RunLambda(Func``1 lambda) rather than RunLambda(Func<string> lambda)

  • value tuples

    Do not match code, output as ValueTuple``2 param rather than (string val, bool) param

  • primitive types

    Do not match code, output as Int64, Boolean, String rather than long, bool, string

  • return types

    Skipped entirely from method signature

Benchmarks

To run benchmarks from the repository root:

dotnet run -p .\test\Ben.Demystifier.Benchmarks\ -c Release -f netcoreapp2.0 All

Note: we're only kicking off via netcoreapp2.0, benchmarks will run for all configured platforms like net462.

ben.demystifier's People

Contributors

alexanderkozlenko avatar alexandersher avatar benaadams avatar bruno-garcia avatar dependabot[bot] avatar drawaes avatar georgeduckett avatar horusiath avatar jnyrup avatar joestead avatar khellang avatar kirillosenkov avatar mitchcapper avatar nickcraver avatar onyxmaster avatar pengweiqhca avatar rgmills avatar samtrion avatar satano avatar sergeyteplyakov avatar sharon-lin avatar simoncropp avatar suchiman avatar tylerap avatar willl avatar zoxive avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ben.demystifier's Issues

Assembly version is missing build and revision numbers

Version 0.0.43 is missing assembly version. When this assembly is references in csproj, it shows as

<Reference Include="Ben.Demystifier, Version=0.0.0.0, Culture=neutral, PublicKeyToken=a6d206e05440431a, processorArchitecture=MSIL">
  <HintPath>..\packages\Ben.Demystifier.0.0.43\lib\net45\Ben.Demystifier.dll</HintPath>
</Reference>

Version 0.0.8 shows as

<Reference Include="Ben.Demystifier, Version=0.0.8.0, Culture=neutral, processorArchitecture=MSIL">
  <HintPath>..\packages\Ben.Demystifier.0.0.8\lib\net45\Ben.Demystifier.dll</HintPath>
</Reference>

While this is not a problem by itself. It does cause breakage in any libraries that depend on Ben.Demystifier.

For example, if codeessentials.Extensions.Logging.Demystifier is installed, it works fine with 0.0.8 ,but loading exception is thrown for 0.0.43 :

Could not load file or assembly 'Ben.Demystifier, Version=0.0.4.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

0.1.2 ToStringDemystified() misses exception detail

			Exception ex = null;
			try
			{
				throw new InvalidOperationException("aaa")
				{
					Data =
					{
						["bbb"] = "ccc",
						["ddd"] = "eee",
					}
				};
			}
			catch (Exception e)
			{
				ex = e;
			}
			var str = ex.ToStringDemystified();

0.1.1 output

System.InvalidOperationException: aaa
   at void Tests.CommonTests.ExceptionDemistyfierTests.TestDemistifyWithData() in D:/.../Infrastructure.Tests/CommonTests/ExceptionDemistyfierTests.cs:line 47

0.1.2 output

   at void Tests.CommonTests.ExceptionDemistyfierTests.TestDemistifyWithData() in D:/.../Infrastructure.Tests/CommonTests/ExceptionDemistyfierTests.cs:line 47

BTW, the corresponding test is broken.

                var original = e.ToString();
                var stringDemystified = e.ToStringDemystified();

                _output.WriteLine("Demystified: ");
                _output.WriteLine(stringDemystified);

                _output.WriteLine("Original: ");
                var afterDemystified = e.ToString(); // <-- here
                _output.WriteLine(afterDemystified);

                Assert.Equal(original, afterDemystified);

IndexOutOfRangeException in ILReader.ReadOpCode() line 36

When analyzing a certain exception I'm seeing an exception in ILReader.ReadOpCode() line 36 here:

return singleByteOpCode[instruction];

The instruction is 235. singleByteOpCode only contains 225 entries.

Stack trace:

>	System.Diagnostics.Internal.ILReader.ReadOpCode Line 36	C#	Symbols loaded.
 	System.Diagnostics.Internal.ILReader.Read Line 25	C#	Symbols loaded.
 	System.Diagnostics.EnhancedStackTrace.TryResolveSourceMethod Line 350	C#	Symbols loaded.
 	System.Diagnostics.EnhancedStackTrace.TryResolveGeneratedName Line 289	C#	Symbols loaded.
 	System.Diagnostics.EnhancedStackTrace.GetMethodDisplayString Line 122	C#	Symbols loaded.
 	System.Diagnostics.EnhancedStackTrace.GetFrames Line 71	C#	Symbols loaded.
 	System.Diagnostics.EnhancedStackTrace.EnhancedStackTrace Line 46	C#	Symbols loaded.

Strong-Naming the assembly

What are the odds of you strong-naming the assembly anytime soon?

I can get around it by repackaging the nuget, but I would rather use yours directly so I can pull updates easily.

Any plans for .NET Native support (UWP in RELEASE mode)?

Hello Ben, I've started using this lib and I have to say so far it's great, you did an awesome job here!
I did some tests with the UWP framework and it looks like the Demistify method fails when the app is compiled in RELEASE mode, ie. when the .NET Native toolchain is enabled.

Here's a simple screen, you can see both the stack traces are the same (the first one is the original, the second is the one extracted after calling Demistify):
image

Are there any plans to support the .NET Native compiler in the future, and is that possible in the first place?

Cheers!
Sergio

System.Runtime.InteropServices.COMException being very annoying!

Got some hairy service fabric traces that contain a number of COMExceptions.

Unfortunately it looks like the stack trace for this can't be cleaned up.

Here's a subset of the stack trace!

System.Runtime.InteropServices.COMException (0x80071BCD): Exception from HRESULT: 0x80071BCD
   at System.Fabric.Interop.NativeClient.IFabricServiceManagementClient6.EndResolveServicePartition(IFabricAsyncOperationContext context)
   at System.Fabric.FabricClient.ServiceManagementClient.ResolveServicePartitionEndWrapper(IFabricAsyncOperationContext context)
   at System.Fabric.Interop.AsyncCallOutAdapter2`1.Finish(IFabricAsyncOperationContext context, Boolean expectedCompletedSynchronously)

What appears to be happening is that in EnhancedStackTrace.GetFrames(Exception) a new StackTrace is constructed from the exception, but that stack trace is empty. I think this is because the _stackTrace field is null, whilst the _stackTraceString field contains the string representation.

So at the moment I don't think anything can be easily done, however it may be worth while putting something in the documentation saying that there are some exceptions that can't be cleaned.

Consider removing asp.net middleware frames

Heres a segment of our stack trace. Note our relevant lines (labelled RiskFabricator) have 10 lines of AspNetCore internals in between.

at async Task RiskFabricator.Controllers.GetRiskController.Get(string product, string version, string base64EnquiryId, CancellationToken cancellationToken) in /build/src/RiskFabricator/Controllers/GetRiskController.cs:line 27
at async Task Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
at async Task Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
at void Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
at Task Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
at async Task Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
at async Task Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
at void Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Task Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
at async Task Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
at async Task Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
at async Task Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at async Task RiskFabricator.HeaderExtractionMiddleware.ExtractEmailHashInformationMiddleware.Invoke(HttpContext context) in /build/src/RiskFabricator/HeaderExtractionMiddleware/ExtractEmailHashInformationMiddleware.cs:line 27

NuGet dependency mismatch between ValueTuple and framework version

The Ben.Demystifier package has these dependencies:
image

I'm using .NET 4.5 and this is causing issues because System.ValueTuple 4.4.0 have the dependency .NETFramework, Version=v4.6.1

Either Ben.Demystifier should also have .NETFramework, Version=v4.6.1 or it should use System.ValueTuple 4.3.1

NuGet package adds duplicate references

I would like to use this, but somehow installing the NuGet package adds a lot of duplicate references to my projects for system packages such as System.Collections, System.ComponentModel, etc.

Using .NET Framework 4.6.2 in my projects. For example, the System.Collections package referenced is:

System.Collections, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.2\Facades\System.Collections.dll

Installing the Demystifier NuGet package adds the duplicate reference:

System.Collections, Version=4.0.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a C:\Program Files (x86)\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\ref\System.Collections.dll

Anything I can do about that?

Add ValueTask support

https://github.com/benaadams/Ben.Demystifier/blob/master/src/Ben.Demystifier/EnhancedStackTrace.Frames.cs#L686

                else if (type == typeof(TaskAwaiter) ||
                    type == typeof(TaskAwaiter<>) ||
+                   type == typeof(ValueTaskAwaiter) ||
+                   type == typeof(ValueTaskAwaiter<>) ||
+                   type == typeof(ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter) ||
+                   type == typeof(ConfiguredValueTaskAwaitable<>.ConfiguredValueTaskAwaiter) ||
                    type == typeof(ConfiguredTaskAwaitable.ConfiguredTaskAwaiter) ||
                    type == typeof(ConfiguredTaskAwaitable<>.ConfiguredTaskAwaiter))
                {

https://github.com/benaadams/Ben.Demystifier/blob/master/src/Ben.Demystifier/Ben.Demystifier.csproj#L17

  <PropertyGroup>
-   <TargetFrameworks>netstandard2.0;net45</TargetFrameworks>
+   <TargetFrameworks>netstandard2.1;netstandard2.0;net45</TargetFrameworks>
  </PropertyGroup>

  <ItemGroup>
+   <PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" Condition="'$(TargetFramework)' != 'netstandard2.1'" />
  </ItemGroup>

Source file paths from SourceLinked binaries aren't appended

I am demystifying a first-chance exception that happens in Roslyn. Roslyn source-links all their assemblies, so the file paths in the .pdb look like:

/_/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs

Unfortunately constructing a new Uri with that string throws:

There are three problems with this:

  1. An additional first-chance exception is generated as a side-effect of demystifying. In a system that I'm building we have tightly controlled first-chance exceptions (and ironically, this is where I'm using Demystify - to pretty-print first-chance exceptions and categorize them properly). Having an avoidable first-chance exception here is a deal-breaker for us.
  2. The source code path for this stack frame is lost.
  3. Since this is happening for every frame with that pattern of source file path, it's a non-trivial perf penalty since the exception is thrown per frame.

I'm thinking if one could avoid constructing a new Uri here and rewrite the code in a different way.

Thanks!

Some stacks cannot be captured because GetMethodDisplayString doesn't handle generic types

  HResult=0x80131509
  Message=Late bound operations cannot be performed on fields with types for which Type.ContainsGenericParameters is true.
  Source=System.Private.CoreLib
  StackTrace:
   at System.Reflection.RtFieldInfo.InternalGetValue(Object obj, StackCrawlMark& stackMark)
   at System.Reflection.RtFieldInfo.GetValue(Object obj)
   at System.Diagnostics.EnhancedStackTrace.GetMethodDisplayString(MethodBase originMethod) in C:\GitHub\Ben.Demystifier\src\Ben.Demystifier\EnhancedStackTrace.Frames.cs:line 142
   at System.Diagnostics.EnhancedStackTrace.GetFrames(StackTrace stackTrace) in C:\GitHub\Ben.Demystifier\src\Ben.Demystifier\EnhancedStackTrace.Frames.cs:line 70
   at System.Diagnostics.EnhancedStackTrace..ctor(StackTrace stackTrace) in C:\GitHub\Ben.Demystifier\src\Ben.Demystifier\EnhancedStackTrace.cs:line 47
   at System.Diagnostics.EnhancedStackTrace.Current() in C:\GitHub\Ben.Demystifier\src\Ben.Demystifier\EnhancedStackTrace.cs:line 14
   at Sparrow.NativeAllocator`1.Initialize(NativeAllocator`1& allocator) in F:\ravendb-4.0\src\Sparrow\Allocators.Native.cs:line 106

The real stack trace is:

   at System.Environment.get_StackTrace()
   at System.Reflection.RtFieldInfo.InternalGetValue(Object obj, StackCrawlMark& stackMark)
   at System.Reflection.RtFieldInfo.GetValue(Object obj)
   at System.Diagnostics.EnhancedStackTrace.GetMethodDisplayString(MethodBase originMethod) in C:\GitHub\Ben.Demystifier\src\Ben.Demystifier\EnhancedStackTrace.Frames.cs:line 142
   at System.Diagnostics.EnhancedStackTrace.GetFrames(StackTrace stackTrace) in C:\GitHub\Ben.Demystifier\src\Ben.Demystifier\EnhancedStackTrace.Frames.cs:line 70
   at System.Diagnostics.EnhancedStackTrace..ctor(StackTrace stackTrace) in C:\GitHub\Ben.Demystifier\src\Ben.Demystifier\EnhancedStackTrace.cs:line 47
   at System.Diagnostics.EnhancedStackTrace.Current() in C:\GitHub\Ben.Demystifier\src\Ben.Demystifier\EnhancedStackTrace.cs:line 14
   at Sparrow.NativeAllocator`1.Initialize(NativeAllocator`1& allocator) in F:\ravendb-4.0\src\Sparrow\Allocators.Native.cs:line 106
   at Sparrow.ArenaAllocator`1.Initialize(ArenaAllocator`1& allocator) in F:\ravendb-4.0\src\Sparrow\Allocators.Arena.cs:line 126
   at Sparrow.Allocator`1.Initialize[TAllocatorOptions](TAllocatorOptions options) in F:\ravendb-4.0\src\Sparrow\Allocators.cs:line 129
   at Sparrow.Json.JsonOperationContext.Renew() in F:\ravendb-4.0\src\Sparrow\Json\JsonOperationContext.cs:line 970
   at Sparrow.Json.JsonContextPoolBase`1.TryReuseExistingContextFrom(ContextStack stack, T& context, IDisposable& disposable) in F:\ravendb-4.0\src\Sparrow\Json\JsonContextPoolBase.cs:line 173
   at Sparrow.Json.JsonContextPoolBase`1.AllocateOperationContext(T& context) in F:\ravendb-4.0\src\Sparrow\Json\JsonContextPoolBase.cs:line 138
   at Sparrow.Json.JsonOperationContext.ManagedPinnedBuffer.Clone[T](JsonContextPoolBase`1 pool) in F:\ravendb-4.0\src\Sparrow\Json\JsonOperationContext.cs:line 215
   at Raven.Server.Documents.Replication.IncomingReplicationHandler..ctor(TcpConnectionOptions options, ReplicationLatestEtagRequest replicatedLastEtag, ReplicationLoader parent, ManagedPinnedBuffer bufferToCopy) in F:\ravendb-4.0\src\Raven.Server\Documents\Replication\IncomingReplicationHandler.cs:line 75
   at Raven.Server.Documents.Replication.ReplicationLoader.AcceptIncomingConnection(TcpConnectionOptions tcpConnectionOptions, ManagedPinnedBuffer buffer) in F:\ravendb-4.0\src\Raven.Server\Documents\Replication\ReplicationLoader.cs:line 248
   at Raven.Server.RavenServer.DispatchDatabaseTcpConnection(TcpConnectionOptions tcp, TcpConnectionHeaderMessage header, ManagedPinnedBuffer bufferToCopy) in F:\ravendb-4.0\src\Raven.Server\RavenServer.cs:line 1469
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at Raven.Server.RavenServer.DispatchDatabaseTcpConnection(TcpConnectionOptions tcp, TcpConnectionHeaderMessage header, ManagedPinnedBuffer bufferToCopy)
   at Raven.Server.RavenServer.<>c__DisplayClass46_0.<<ListenToNewTcpConnection>b__0>d.MoveNext() in F:\ravendb-4.0\src\Raven.Server\RavenServer.cs:line 1289
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.<>c.<OutputWaitEtwEvents>b__12_0(Action innerContinuation, Task innerTask)
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining)
   at System.Threading.Tasks.Task.RunContinuations(Object continuationObject)
   at System.Threading.Tasks.Task`1.TrySetResult(TResult result)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(TResult result)
   at Sparrow.Json.JsonOperationContext.ParseToMemoryAsync(Stream stream, String documentId, UsageMode mode, ManagedPinnedBuffer bytes, Nullable`1 token, Int32 maxSize) in F:\ravendb-4.0\src\Sparrow\Json\JsonOperationContext.cs:line 942
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.<>c.<OutputWaitEtwEvents>b__12_0(Action innerContinuation, Task innerTask)
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining)
   at System.Threading.Tasks.Task.RunContinuations(Object continuationObject)
   at System.Threading.Tasks.Task`1.TrySetResult(TResult result)
   at System.Threading.Tasks.ValueTask`1.ValueTaskSourceAsTask.<>c.<.cctor>b__4_0(Object state)
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.InvokeContinuation(Action`1 continuation, Object state, Boolean forceAsync)
   at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.OnCompleted(SocketAsyncEventArgs _)
   at System.Net.Sockets.SocketAsyncEventArgs.FinishOperationAsyncSuccess(Int32 bytesTransferred, SocketFlags flags)
   at System.Net.Sockets.SocketAsyncEventArgs.<>c.<.cctor>b__177_0(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

Path separater is "wrong" on Windows

Maybe this is "as designed", but I noticed that Ben.Demystifier uses forward-slashes for path separators, and not backslashes, as the normal exception stack trace on Windows. It this intentional, for it to be the same across all platforms, or unintentional?

Stack trace for generic types with tuples is incorrect

Here is an example:

async Task<(int left, int right)> AsyncThatReturnsTuple()
{
        await Task.Delay(1).ConfigureAwait(false);
        throw new ArgumentException();
}

In this case the demystified exception looks like this:

at async (ValueTuple<int, int> left) ConsoleApp11.Program.AsyncWithTuple() 

But should be

at async Task<(int left, int right)> ConsoleApp11.Program.AsyncWithTuple() 

Demystify some more esoteric stack traces

Hi!

Is it possible to improve readability of the bold marked lines?

Application startup exception: System.Net.Sockets.SocketException (61): Connection refused
at Npgsql.NpgsqlConnector.Connect(NpgsqlTimeout timeout) in C:\projects\npgsql\src\Npgsql\NpgsqlConnector.cs:line 704
at Npgsql.NpgsqlConnector.RawOpen(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken) in C:\projects\npgsql\src\Npgsql\NpgsqlConnector.cs:line 555
at Npgsql.NpgsqlConnector.Open(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken) in C:\projects\npgsql\src\Npgsql\NpgsqlConnector.cs:line 414
at Npgsql.NpgsqlConnection.<>c__DisplayClass32_0.<g__OpenLong|0>d.MoveNext() in C:\projects\npgsql\src\Npgsql\NpgsqlConnection.cs:line 272
--- End of stack trace from previous location where exception was thrown ---
at Npgsql.NpgsqlConnection.Open() in C:\projects\npgsql\src\Npgsql\NpgsqlConnection.cs:line 153
at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlDatabaseCreator.Exists() in C:\projects\npgsql-entityframeworkcore-postgresql\src\EFCore.PG\Storage\Internal\NpgsqlDatabaseCreator.cs:line 216
at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists()
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.Migrate(DatabaseFacade databaseFacade)
at Sapphire.EntityFrameworkCore.Extensions.ServiceProviderExtensions.MigrateDatabase[TContext](IServiceProvider serviceProvider) in /Users/krisztian.kocsis/Documents/Projects/miw-cloud/modules/sapphire/src/Sapphire.EntityFrameworkCore/Extensions/ServiceProviderExtensions.cs:line 41
at MIW.Cloud.Web.Bootstrap.Configure(IApplicationBuilder applicationBuilder) in /Users/krisztian.kocsis/Documents/Projects/miw-cloud/src/MIW.Cloud.Web/Bootstrap.cs:line 135
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.b__0(IApplicationBuilder app)
at Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.b__0(IApplicationBuilder builder)
at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()

Local function with method invocation on variable from outer scope

I have discovered erroneous behavior with local function. Here a small app to reproduce:

internal class Program
{
    private static async Task Main(string[] args)
    {
        int number = default;
        try
        {
            await Fun();
            
            async Task Fun()
            {
                number.ToString();
                throw new Exception();
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Demystify());
        }
}

Execution of the code above produces following stack trace:

System.Exception: Exception of type 'System.Exception' was thrown.
   at void Program+<>c__DisplayClass0_0+<<Main>g__Fun|0>d.MoveNext()
   at async Task Program.Main(string[] args)

If I remove number.ToString(); it produces expected stack trace.

Error parsing stack trace (in ILReader.ReadOpCode)

I'm getting the following error in my logs:

IndexOutOfRangeException:
Message: Index was outside the bounds of the array.
Stack trace:
	at OpCode System.Diagnostics.Internal.ILReader.ReadOpCode()
	at bool System.Diagnostics.Internal.ILReader.Read(MethodBase methodInfo)
	at bool System.Diagnostics.EnhancedStackTrace.TryResolveSourceMethod(IEnumerable<MethodBase> candidateMethods, GeneratedNameKind kind, string matchHint, ref MethodBase method, ref Type type, out Nullable<int> ordinal)
	at bool System.Diagnostics.EnhancedStackTrace.TryResolveGeneratedName(ref MethodBase method, out Type type, out string methodName, out string subMethodName, out GeneratedNameKind kind, out Nullable<int> ordinal)
	at ResolvedMethod System.Diagnostics.EnhancedStackTrace.GetMethodDisplayString(MethodBase originMethod)
	at List<EnhancedStackFrame> System.Diagnostics.EnhancedStackTrace.GetFrames(StackTrace stackTrace)
	at List<EnhancedStackFrame> System.Diagnostics.EnhancedStackTrace.GetFrames(Exception exception)
	at new System.Diagnostics.EnhancedStackTrace(Exception e)
	at new DDS.Runtime.Diagnostics.Data.Details.ExceptionDetailBuilder(Exception exception)

Since I'm catching possible errors in Demystifier, when this happens, I store the original stack trace unmodified, so the above error was related to this stack trace:

Message: Unable to connect to any of the specified MySQL hosts.
Stack trace:
	   at MySqlConnector.Core.ServerSession.<ConnectAsync>d__56.MoveNext() in C:\projects\mysqlconnector\src\MySqlConnector\Core\ServerSession.cs:line 215
	--- End of stack trace from previous location where exception was thrown ---
	   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
	   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
	   at MySql.Data.MySqlClient.MySqlConnection.<CreateSessionAsync>d__77.MoveNext() in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlConnection.cs:line 365
	--- End of stack trace from previous location where exception was thrown ---
	   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
	   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
	   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
	   at MySql.Data.MySqlClient.MySqlConnection.<OpenAsync>d__19.MoveNext() in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlConnection.cs:line 160
	--- End of stack trace from previous location where exception was thrown ---
	   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
	   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
	   at MySql.Data.MySqlClient.MySqlConnection.Open() in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlConnection.cs:line 137
	   at Microsoft.EntityFrameworkCore.Storage.Internal.MySqlConnectionSettings.<>c__DisplayClass2_0.<GetSettings>b__0(String key)
	   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
	   at Microsoft.EntityFrameworkCore.Storage.Internal.MySqlConnectionSettings.GetSettings(String connectionString)
	   at Microsoft.EntityFrameworkCore.Internal.MySqlOptions.<.ctor>b__2_0()
	   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
	--- End of stack trace from previous location where exception was thrown ---
	   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
	   at System.Lazy`1.CreateValue()
	   at Microsoft.EntityFrameworkCore.Internal.MySqlOptions.get_ConnectionSettings()
	   at Microsoft.EntityFrameworkCore.Storage.Internal.MySqlSmartTypeMapper.MaybeConvertMapping(RelationalTypeMapping mapping)
	   at Microsoft.EntityFrameworkCore.Storage.Internal.MySqlSmartTypeMapper.FindMapping(Type clrType)
	   at Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapper.IsTypeMapped(Type clrType)
	   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.PropertyDiscoveryConvention.IsCandidatePrimitiveProperty(PropertyInfo propertyInfo)
	   at System.Linq.Enumerable.WhereArrayIterator`1.MoveNext()
	   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.PropertyDiscoveryConvention.Apply(InternalEntityTypeBuilder entityTypeBuilder)
	   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnEntityTypeAdded(InternalEntityTypeBuilder entityTypeBuilder)
	   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnEntityTypeAdded(InternalEntityTypeBuilder entityTypeBuilder)
	   at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.AddEntityType(EntityType entityType)
	   at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.AddEntityType(Type type, ConfigurationSource configurationSource)
	   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(TypeIdentity type, ConfigurationSource configurationSource)
	   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(Type type, ConfigurationSource configurationSource)
	   at Microsoft.EntityFrameworkCore.ModelBuilder.Entity(Type type)
	   at Microsoft.EntityFrameworkCore.Infrastructure.ModelCustomizer.FindSets(ModelBuilder modelBuilder, DbContext context)
	   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelCustomizer.FindSets(ModelBuilder modelBuilder, DbContext context)
	   at Microsoft.EntityFrameworkCore.Infrastructure.ModelCustomizer.Customize(ModelBuilder modelBuilder, DbContext context)
	   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelCustomizer.Customize(ModelBuilder modelBuilder, DbContext context)
	   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)
	   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.<>c__DisplayClass5_0.<GetModel>b__0(Object k)
	   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
	   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)
	   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
	   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
	   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_1(IServiceProvider p)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProvider provider)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(IServiceCallSite callSite, ServiceProvider provider)
	   at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass22_0.<RealizeService>b__0(ServiceProvider provider)
	   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
	   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
	   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_10(IServiceProvider p)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProvider provider)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, ServiceProvider provider)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)
	   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(IServiceCallSite callSite, ServiceProvider provider)
	   at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass22_0.<RealizeService>b__0(ServiceProvider provider)
	   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
	   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
	   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Internal.IDbContextPoolable.ResetState()
	   at Microsoft.EntityFrameworkCore.Internal.DbContextPool`1.Return(TContext context)
	   at Microsoft.EntityFrameworkCore.Internal.DbContextPool`1.Microsoft.EntityFrameworkCore.Internal.IDbContextPool.Return(DbContext context)
	   at Microsoft.EntityFrameworkCore.DbContext.Dispose()
	   at Microsoft.Extensions.DependencyInjection.ServiceProvider.Dispose()
	   at Microsoft.AspNetCore.Hosting.Internal.WebHost.Dispose()

GetMethodDisplayString incorrectly decodes nested lambda

I'm using EnhancedStackTrace.GetMethodDisplayString on its own to decode the name of a lambda nested in another lambda, but the result is not correct.

Specifically, it reproduces with this code:

using System;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        void Execute(Action a) => a();

        Execute(() =>
        {
            Action b = () => {};

            Console.WriteLine(EnhancedStackTrace.GetMethodDisplayString(b.Method));
        });
    }
}

This prints void Program+<>c.<Main>b__0_2(?)+() => { }, which still looks mystifying.

This code decompiles to:

internal class Program
{
    [CompilerGenerated]
    [Serializable]
    private sealed class <>c
    {
        public static readonly Program.<>c <>9 = new Program.<>c();

        public static Action <>9__0_2;

        public static Action <>9__0_1;

        internal void <Main>b__0_1()
        {
            Action arg_1F_0;
            if ((arg_1F_0 = Program.<>c.<>9__0_2) == null)
            {
                Program.<>c.<>9__0_2 = (arg_1F_0 = new Action(Program.<>c.<>9.<Main>b__0_2));
            }
            Console.WriteLine(EnhancedStackTrace.GetMethodDisplayString(arg_1F_0.Method));
        }

        internal void <Main>b__0_2()
        {
        }
    }

    private static void Main()
    {
        Action arg_1F_0;
        if ((arg_1F_0 = Program.<>c.<>9__0_1) == null)
        {
            Program.<>c.<>9__0_1 = (arg_1F_0 = new Action(Program.<>c.<>9.<Main>b__0_1));
        }
        Program.<Main>g__Execute0_0(arg_1F_0);
    }

    [CompilerGenerated]
    internal static void <Main>g__Execute0_0(Action a)
    {
        a();
    }
}

Support filtering frames

We've hit a scenario where we want to reduce additional noise from framework components to cut down logging costs.

Specific scenario we have is with ASP.NET MVC and ActionFilterAttributes, we have several registered and it results in a fair amount of excessive information in the logs, for example:

   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecutedAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
   at async Task<HttpResponseMessage> System.Web.Http.Filters.ActionFilterAttribute.ExecuteActionFilterAsyncCore(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)

This is included in any stack trace as from our API and represents about 75% of the stacktrace itself. Do you think there would be value in supporting some filtering mechanism to allow consumers to reduce the output?

Could not load file or assembly 'Ben.Demystifier, Version=0.1.0.0 ...

Attempting to use Ben.Demystifier version 0.1.4 installed via NuGet. I am getting the following error at runtime.

Looks like the version number is not getting set correctly?

Could not load file or assembly 'Ben.Demystifier, Version=0.1.0.0, Culture=neutral, PublicKeyToken=a6d206e05440431a' or one of its dependencies. The system cannot find the file specified.

Error: Index was outside the bounds of the array.

I just saw this on my logs:

23-11-2017 19:49:53:782: [Error ] ProcessRequestAsync IndexOutOfRangeException: Message: Index was outside the bounds of the array. Stack trace: at ParameterInfo Attribute.GetParentDefinition(ParameterInfo param) at Attribute[] Attribute.InternalParamGetCustomAttributes(ParameterInfo param, Type type, bool inherit) at IEnumerable<T> System.Reflection.CustomAttributeExtensions.GetCustomAttributes<T>(ParameterInfo element) at ResolvedParameter System.Diagnostics.EnhancedStackTrace.GetParameter(ParameterInfo parameter) at ResolvedMethod System.Diagnostics.EnhancedStackTrace.GetMethodDisplayString(MethodBase originMethod) at List<EnhancedStackFrame> System.Diagnostics.EnhancedStackTrace.GetFrames(StackTrace stackTrace) at List<EnhancedStackFrame> System.Diagnostics.EnhancedStackTrace.GetFrames(Exception exception) at new System.Diagnostics.EnhancedStackTrace(Exception e) at new DDS.Runtime.Diagnostics.Data.Details.ExceptionDetailBuilder(Exception exception) at ILogEntry DDS.Runtime.Diagnostics.Logger.Write(LogEventType eventType, string message, Exception exception, LogEntryData data) at ILogEntry DDS.Runtime.Diagnostics.Primitives.DiagnosticsPrimitivesExtensions.LogError(ILogger logger, Exception exception, LogEntryData data) at void DDS.AspNetCore.Mvc.Filters.StatusExceptionFilter.OnException(ExceptionContext context) at Task Microsoft.AspNetCore.Mvc.Filters.ExceptionFilterAttribute.OnExceptionAsync(ExceptionContext context) at Task Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) at async Task Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() at void Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) at Task Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) at async Task Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() at async Task Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync() at async Task Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext) at async Task Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) at async Task Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context) at async Task Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at async Task Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware.Invoke(HttpContext context) at async Task Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.Invoke(HttpContext httpContext) at async void Microsoft.AspNetCore.Server.HttpSys.MessagePump.ProcessRequestAsync(object requestContextObj) at async void Microsoft.AspNetCore.Server.HttpSys.MessagePump.ProcessRequestAsync(object requestContextObj)

Not sure what the original error was.... I'm trying to reproduce locally and post any additional information...

Expose cleaned up Exception

Right now when an exception is .Demystify() it exposes a cleaned up stack trace.
The issue is, I'm using Bugsnag (probably not the only library) that takes the exception and builds some internal structure (StackTraceLine - https://github.com/bugsnag/bugsnag-dotnet/blob/96360fb0f8d31f5fd6a8f3f17184bd626421820e/src/Bugsnag/Payload/Exception.cs#L85) before logging it. Therefore, the Demystifier has no effect.

Can we please get a Demystify() that cleans up the stack frames as well so that if the exception is used in another library it will not include the unnecessary stack frames?

.Net4.0 Support

Hi,
It would be great if this package target .net4.0 as it is the last Long Term release and heavily deployed. Also, it would be great if Demystifier can work in StackTrace string as that would really much increase its usability even in CI Servers to post-process data.

Thanks for this great package

Assemblies in NuGet package are not signed with Authenticode

Is it possible to sign the assemblies with Authenticode ?

C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x64>signtool verify "C:\Users\sezhezhe\.nuget\packages\ben.demystifier\0.1.4\lib\netstandard2.0\Ben.Demystifier.dll"
File: C:\Users\sezhezhe\.nuget\packages\ben.demystifier\0.1.4\lib\netstandard2.0\Ben.Demystifier.dll
Index  Algorithm  Timestamp
========================================
SignTool Error: No signature found.

Number of errors: 1

ToStringDemystified() doesn't use the standard ToString() pattern for inner exceptions

Consider the following LINQPad code:

void Main()
{
	try { Foo(); }
	catch (Exception e)
	{
		e.ToString().Dump("ToString");
		e.ToStringDemystified().Dump("ToStringDemystified");
		e.Demystify().ToString().Dump(".Demystify().ToString()");
	}
}

public void Foo()
{
	try { Bar();} catch(Exception e) {throw new InvalidOperationException("Something failed while trying to Bar", e);}
}
public void Bar()
{
	try { Baz(); } catch (Exception e) { throw new InvalidOperationException("Something failed while trying to Baz", e); }
}
public void Baz()
{
	throw new InvalidOperationException("Something went wrong in here");
}

Output for .Demystify().ToString() looks like this:

System.InvalidOperationException: Something failed while trying to Bar ---> System.InvalidOperationException: Something failed while trying to Baz ---> System.InvalidOperationException: Something went wrong in here
   at void UserQuery.Bar() in C:/Users/james.jensen/AppData/Local/Temp/LINQPad5/_pwdvguda/query_wparci.cs:line 47
   --- End of inner exception stack trace ---
   at void UserQuery.Bar() in C:/Users/james.jensen/AppData/Local/Temp/LINQPad5/_pwdvguda/query_wparci.cs:line 47
   at void UserQuery.Foo() in C:/Users/james.jensen/AppData/Local/Temp/LINQPad5/_pwdvguda/query_wparci.cs:line 43
   --- End of inner exception stack trace ---
   at void UserQuery.Foo() in C:/Users/james.jensen/AppData/Local/Temp/LINQPad5/_pwdvguda/query_wparci.cs:line 43
   at void UserQuery.Main() in C:/Users/james.jensen/AppData/Local/Temp/LINQPad5/_pwdvguda/query_wparci.cs:line 31

Output for .ToStringDemystified() looks like this:

System.InvalidOperationException: Something failed while trying to Bar
   at void UserQuery.Foo() in C:/Users/james.jensen/AppData/Local/Temp/LINQPad5/_pwdvguda/query_wparci.cs:line 43
   at void UserQuery.Main() in C:/Users/james.jensen/AppData/Local/Temp/LINQPad5/_pwdvguda/query_wparci.cs:line 31 ---> System.InvalidOperationException: Something failed while trying to Baz
   at void UserQuery.Bar() in C:/Users/james.jensen/AppData/Local/Temp/LINQPad5/_pwdvguda/query_wparci.cs:line 47
   at void UserQuery.Foo() in C:/Users/james.jensen/AppData/Local/Temp/LINQPad5/_pwdvguda/query_wparci.cs:line 43 ---> System.InvalidOperationException: Something went wrong in here
   at void UserQuery.Bar() in C:/Users/james.jensen/AppData/Local/Temp/LINQPad5/_pwdvguda/query_wparci.cs:line 47
   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---

I believe this changed in a recent patch version update. (Tested on 0.1.4)

Some System.Web.Mvc DisplayName methods unresolved

I have a stacktrace line that, after prettifying looks like this:

at void System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass21+<>c__DisplayClass2b.<BeginInvokeAction>b__1c(?)+()=>{}

It looks like it can't find a pdb file for System.Web.Mvc, which resides in the Temporary ASP.NET directory. Could that have something to do with it (and is there anything I can do to make the/a pdb available)?

Is this expected output or could this be prettified further?

Missing Assemblies because of System.ValueTuple?

Probably not a bug, but maybe a good thing to put in readme?
I installed this on a net 461 project yesterday. We ran into weird problems, for example a referenced project couldnt find System.Net.Http 4.2.0.0.

I thought maybe net462 was needed so we tried to upgrade. Still the asme problem.

Tried to Run Add-BindingRedirect etc.
Tried upgrading all the way to net471.

Never got it to run. If I removed Ben.Demystifier it all worked again.

Any clues on how to resolve this?

Support .NET 4.5

The nugget package target .NET4.6 which mean we can't use it on our .NET4.5 projects.
Thanks you for the greatness !!

Aggregate exceptions

Great library! Biggest problem with doing good work is people raise awkward questions! Sorry.

What's the best way to handle AggregateExceptions? I'm using Service Fabric and Serilog for all my logging. Lots of cross service exceptions are exposed as AggregateExceptions and they still produce a generally old fashioned stack trace.

I've got something working by just logging the inner exception, but that seems like I'm handling the problem at the wrong level. I think Demystify should handle the aggregate exception internally.

This change in Demystify may work - does it make sense?

                if (exception is AggregateException aex)
                {
                    foreach (var innerException in aex.InnerExceptions)
                    {
                        innerException.Demystify();
                    }
                }
                else
                {
                    exception.InnerException?.Demystify();
                }

async lambda not Demystified

Throwing from async lambda like so

namespace SomeNamespace
{
  public static class SomeClass
  {
    public static void ThrowsSomethingAsync()
    {
      Func<Task> f = async () => throw new Exception("Some exception");
      f().ConfigureAwait(false).GetAwaiter().GetResult();
    }
  }
}

Transforms

   at SomeNamespace.SomeClass.<>c.<<ThrowsSomethingAsync>b__0_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
   at SomeNamespace.SomeClass.ThrowsSomethingAsync()

into

   at void SomeNamespace.SomeClass+<>c+<<ThrowsSomethingAsync>b__0_0>d.MoveNext()
   at void SomeNamespace.SomeClass.ThrowsSomethingAsync()

without async I get

   at void SomeNamespace.SomeClass.ThrowsSomethingAsync()+() => { }
   at void SomeNamespace.SomeClass.ThrowsSomethingAsync()

EnhancedStackTrace fails on exceptions without stack trace

When I have an exception that was not thrown, it does not have any stack trace (null is in StackTrace) and EnhancedStackTrace fails on that. It kind of makes sense, as there is no stack trace, but I think it would be nicer if would return an empty list or propagate the null.

The problem is that this error check returns null from GetFrames and later it throws NullReferenceException on all places that touch _frames. I think that it would better to return an empty list in these cases.

Support for html/custom formatting

Hi,

This library is great for improving a raw stacktrace (thanks!). I'd love to be able to easily format its output for display on a web page or email too, without having to resort to Regex or parsing the string output.

Looking at the various Append methods it looks like this should be possible, however I'm not quite sure what an API would look like, or whether this request belongs within this library at all.

My first thought would be creating equivalent methods to the Append ones that returned an enumerable token list (consisting of string and token type) rather than appending to a StringBuilder. The consumer could then iterate over the list inserting formatting sections between the strings as appropriate. Another option could be simply surrounding relevant output with <span> tags, however this would be pretty inflexible and would have to handle html encoding. An 3rd option could be creating a FormatSettings class that defines various strings to insert before/after certain tokens.

Would be great to hear any thoughts on the above.

The PDB reader occasionally fails with file access exception

System.IO.IOException: The process cannot access the file 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\6dac5fe0\f282cd8a\assembly\dl3\5032d4d4\5885728e_c5e2d301\WebApp.Compiled.pdb' because it is being used by another process.
void System.IO.__Error.WinIOError(int errorCode, string maybeFullPath)
void System.IO.FileStream.Init(string path, FileMode mode, FileAccess access, int rights, bool useRights, FileShare share, int bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, string msgPath, bool bFromProxy, bool useLongPath, bool checkHost)
new System.IO.FileStream(string path, FileMode mode, FileAccess access, FileShare share)
bool System.Diagnostics.Internal.PortablePdbReader.IsPortable(string pdbPath)
MetadataReader System.Diagnostics.Internal.PortablePdbReader.GetMetadataReader(string assemblyPath)
void System.Diagnostics.Internal.PortablePdbReader.PopulateStackFrame(StackFrame frameInfo, MethodBase method, int IlOffset, out string fileName, out int row, out int column)
List<EnhancedStackFrame> System.Diagnostics.EnhancedStackTrace.GetFrames(StackTrace stackTrace)
new System.Diagnostics.EnhancedStackTrace(StackTrace stackTrace)
...

I checked the code for PortablePdbReader and it seems that it opens the files with proper sharing mode (via File.OpenRead), so I have no idea why it can fail or who else could be opening the PDB (this is an ASP.NET 4.5 application running in IIS 8), but I believe I still have to report this.
I'm going to place an IOException handler around calls to the Demystifier methods in our code to handle cases like these, and I think you could consider doing the same.

Add extension to demystify StackTrace

In some cases we're logging stack traces using new StackTrace() and it would be nice to have an extension that would demystify the StackTrace alone. For now I've hacked it internally by using new EnhancedStackTrace(new StackTrace()) but maybe such extension method would be useful for others as well? If you think it's a good idea I can prepare a PR for it.

Incorrect paths are constructed for source locations when compiled on Windows but run on !Windows

When running a program that I compiled on Windows (standalone .NET Core app, compiled via dotnet publish -o foo -c Release -r ubuntu16.04-arm for a RPi), I get demystified stack traces that have the absolute Windows paths from the PDBs appended to the current working directory of the app on Linux:

System.FormatException: Input string was not in a correct format.
     at float Number.ParseSingle(string value, NumberStyles options, NumberFormatInfo numfmt)
     at BellowsRecord ZigBeeGrapher.Program+BellowsRecord.Parse(string line) in /home/pi/zigbee-grapher/C:\Users\BojanRajkovic\source\repos\ZigBeeGrapher\Program.cs:line 351
     at async Task ZigBeeGrapher.Program.ProcessCsvLinesAsync(IList<string> csvLines) in /home/pi/zigbee-grapher/C:\Users\BojanRajkovic\source\repos\ZigBeeGrapher\Program.cs:line 90

I haven't explored a whole ton, but I suspect there's some absolute path detection that isn't considering this scenario.

Edit: Looks like this code is the culprit: https://github.com/benaadams/Ben.Demystifier/blob/master/src/Ben.Demystifier/EnhancedStackTrace.cs#L110.

GetParameter throws on Task<object> on GetCustomAttributes<TupleElementNamesAttribute>

var tupleNames = parameter.GetCustomAttributes<TupleElementNamesAttribute>().FirstOrDefault()?.TransformNames;

Throws an index of out range exception when there are no custom attributes.

Specific type where I saw it was

System.Threading.Tasks.Task`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Running on .NET 4.6.2

Full type name for method parameters

Type name for a method parameter should include the corresponding namespace if the type is a non-BCL type.

Example:

namespace n
{
    class t
    {
        public void m(object p0, n1.t1 p1) => m(null, null as n2.t1);
        public void m(object p0, n2.t1 p1) => throw new Exception();
    }
}

namespace n1
{
    class t1 { }
}

namespace n2
{
    class t1 { }
}

new n.t().m(null, null as n1.t1)

Current behavior

void n.t.m(object p0, t1 p1)
void n.t.m(object p0, t1 p1)

Expected behavior:

void n.t.m(object p0, n2.t1 p1)
void n.t.m(object p0, n1.t1 p1)

Add source to the repo

Please provide the source in this repository. Looking at the readme, this thing would be really valuable to already use. Good stuff building this 🥇 .

I can imagine that this is still very much in flux, and rough around the edges, but this thing would already be a great help to understand some weird stacktraces that I see every day. So I would be fine with something that not really finished yet (I'll get it to work).

If there could be a way for already using this, I'd greatly appreciate it. 🎉

Not compatible with Microsoft.CodeAnalysis.Csharp

First of all thanks a lot, it's very useful to have relevant StackTraces.

Unfortunately I am one of these poor guy that needs to use strongnames. So we used strongnamer which works perfectly. However once you strongname you really need similar versions.

Ben.Demystifier requires System.Reflection.Metadata 1.5.0, which requires System.Collections.Immutable 1.4.0

We also use Microsoft.CodeAnalysis.Csharp, but unfortunately it uses Microsoft.CodeAnalysis.Common 2.4.0, which uses System.Collections.Immutable 1.3.1

So when running the runtime is obviously unhappy.
Do you see a way to make both cohabit?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.