Ben.Demystifier

其他类别 2025-08-25

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

  • 参数

    请勿指定预选赛refoutin

  • 迭代器

    无法确定过载d__3.MoveNext()而不是Iterator(int startAt)+MoveNext()

  • linq

    无法确定超负荷

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

    而不是

    Linq.Enumerable+SelectEnumerableIterator.MoveNext()

  • 异步

    无法确定过载,也无法确定诸如async修饰符

    d__5``1.MoveNext()

    而不是

    async Task 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 g__LocalFuncParam|10_0(String val, <>c__DisplayClass10_0& )建议他们声明的位置,但如果该方法有多个过载,则没有提示。

  • 通用参数

    无法解决,仅指示数字RunLambda(Func``1 lambda)而不是RunLambda(Func lambda)

  • 价值元组

    请勿匹配代码,将输出作为ValueTuple``2 param而不是(string val, bool) param

  • 原始类型

    不匹配代码,输出为Int64BooleanString而不是longboolstring

  • 返回类型

    完全从方法签名跳过

基准

从存储库根运行基准:

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

注意:我们只通过netcoreapp2.0开始,基准将用于所有配置的平台(如net462

下载源码

通过命令行克隆项目:

git clone https://github.com/benaadams/Ben.Demystifier.git