Async-friendly format for stack traces and exceptions
Async-friendly format for stack traces and exceptions.
Also check out Ben's Demystifier which resolves async, iterators, tuples, location functions and more.
System.Exception: Crash! Boom! Bang! at async AsyncFriendlyStackTrace.Test.Example1.C(?) in C:\Source\Repos\AsyncFriendlyStackTrace\src\AsyncFriendlyStackTrace.Test\Example1.cs:line 26 at async AsyncFriendlyStackTrace.Test.Example1.B(?) in C:\Source\Repos\AsyncFriendlyStackTrace\src\AsyncFriendlyStackTrace.Test\Example1.cs:line 20 at async AsyncFriendlyStackTrace.Test.Example1.A(?) in C:\Source\Repos\AsyncFriendlyStackTrace\src\AsyncFriendlyStackTrace.Test\Example1.cs:line 15 at async AsyncFriendlyStackTrace.Test.Example1.Run(?) in C:\Source\Repos\AsyncFriendlyStackTrace\src\AsyncFriendlyStackTrace.Test\Example1.cs:line 10 at AsyncFriendlyStackTrace.Test.Program.Run[TExample](TextWriter writer) in C:\Source\Repos\AsyncFriendlyStackTrace\src\AsyncFriendlyStackTrace.Test\Program.cs:line 45
Install-Package AsyncFriendlyStackTrace
To format exceptions, use the extension methods in
ExceptionExtensions:
exception.ToAsyncString();
This produces an async-friendly format, as you can see in the examples below. There is also special handling for
AggregateExceptions and
ReflectionTypeLoadException(which can contain multiple inner exceptions).
The main formatting work is done by the
StackTraceExtensions.ToAsyncStringextension method. The async-friendly formatting is archieved by: * Skipping all awaiter frames (all methods in types implementing
INotifyCompletion) and
ExceptionDispatchInfoframes. * Inferring the original method name from the async state machine class (
IAsyncStateMachine) and removing the "MoveNext" - currently only for C#. * Adding the "async" prefix after "at" on each line for async invocations. * Appending "(?)" to the method signature to indicate that parameter information is missing. * Removing the "End of stack trace from previous location..." text.
In all the examples, OLD refrers to
ToString()output, while NEW is
ToAsyncString().
Wait()in the middle, causing an
AggregateException.
AggregateExceptionformatting (the first inner exception isn't repeated twice).
PrepareForAsyncSerializationbefore serializing the exception. This saves the async-friendly stack trace as a string in the
Datadictionary of the exception. This has two downsides:
DataContractSerializer, you must include
exception.Data.GetType()as a known type. This is because its concrete type (
ListDictionaryInternal) is internal.