Ben.Demystifier
在堆栈跟踪中输出现代C#7.0+功能,看起来像C#源代码生成它们而不是格式化。
对堆栈痕迹的高性能理解
.NET堆栈跟踪输出编译器转换方法;而不是源代码方法,这使它们在精神上解析并与源代码匹配。
当前的输出适用于C#1.0;但是,由于C#2.0(迭代器,仿制药)随着新功能的添加到.NET语言,并且在C#7.1堆栈痕迹是深奥的(请参阅:当前堆栈痕迹的问题),因此变得越来越糟。
使错误日志提高生产力
以可理解的方式输出堆栈跟踪中的现代C#7.0+功能,看起来像生成它们的C#源代码。
用法
exception.Demystify()
或而不是环境.stacktrace
EnhancedStackTrace.Current()
将堆栈解析回呼叫的C#源格式(并且是可检查的堆栈框架列表)
demystified异常上的呼叫.ToString()将产生类似于以下的字符串stacktrace(没有注释):
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 )
在同一例外情况下调用.ToString()将产生以下输出
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 )
它的帮助远不多
当前堆栈跟踪的问题:
-
构造函数
不匹配代码,输出为
.ctor和.cctor -
参数
请勿指定预选赛
ref,out或in -
迭代器
无法确定过载
<Iterator>d__3.MoveNext()而不是Iterator(int startAt)+MoveNext() -
linq
无法确定超负荷
Linq.Enumerable.SelectEnumerableIterator``2.MoveNext()而不是
Linq.Enumerable+SelectEnumerableIterator<TSource, TResult>.MoveNext() -
异步
无法确定过载,也无法确定诸如
async修饰符<MethodAsync>d__5``1.MoveNext()而不是
async Task<string> Program.MethodAsync(int value)噪音!
--- 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
主要是jibberish
<>c__DisplayClass2_0.<.ctor>b__0(Object state)建议他们声明的位置,但如果该方法有多个过载,则没有提示。 -
本地功能
大多数是Jibberish
<RefMethod>g__LocalFuncParam|10_0(String val, <>c__DisplayClass10_0& )建议他们声明的位置,但如果该方法有多个过载,则没有提示。 -
通用参数
无法解决,仅指示数字
RunLambda(Func``1 lambda)而不是RunLambda(Func<string> lambda) -
价值元组
请勿匹配代码,将输出作为
ValueTuple``2 param而不是(string val, bool) param -
原始类型
不匹配代码,输出为
Int64,Boolean,String而不是long,bool,string -
返回类型
完全从方法签名跳过
基准
从存储库根运行基准:
dotnet run -p .\\test\\ Ben.Demystifier .Benchmarks\\ -c Release -f netcoreapp2.0 All
注意:我们只通过netcoreapp2.0开始,基准将用于所有配置的平台(如net462 。
