web-dev-qa-db-ja.com

呼び出されたすべてのメソッドをトレースする方法

実行中のすべての呼び出しを確認し、ログファイルにダンプしたい既存のプロジェクトがあります。

私は見てみた このスレッドで だが、あまり役に立たなかった。私はPostSharpを試してみましたが、例ではそれを実現する方法を示しています。しかし、すべてのdarnメソッドに属性を追加する必要があります。既存のプロジェクトであり、実行可能なオプションではない多数の方法がある。

行われたすべての呼び出しをすばやく追跡できる他の方法はありますか?

26
ShaQ.Blogs

nity Interception でこれを行うことができます

この サンプルの記事 を参照してください。記事では属性を使用していますが、以下のコードサンプルでは、​​依存関係注入システム(インターフェースへのコーディング)を使用してインターセプトをセットアップしています。

MyClassをログに記録する場合は、次のようになります。

  1. MyClass => IMyClassのすべてのメソッドを含むインターフェースを作成します
  2. (以下で行ったように)InterfaceInterceptionをセットアップしますORセットアップできる他の方法がいくつかあります。 すべてのオプションについてはこちら を参照してください。
  3. IMatchingRuleに一致するすべてのメソッドをインターセプトするポリシーを設定します。
  4. すべての呼び出しが ICallHandler 実装によってインターセプトされるようになります。

コード:

//You  will use the code like this:
MyContainer container = new MyContainer();
//setup interception for this type..
container.SetupForInteception(typeof(IMyClass));
 //what happens here is you get a proxy class 
 //that intercepts every method call.
IMyClass cls = container.Resolve<IMyClass>();

 //You need the following for it to work:   
public class MyContainer: UnityContainer
{
    public MyContainer()
    {
        this.AddNewExtension<Interception>();
        this.RegisterType(typeof(ICallHandler), 
                    typeof(LogCallHandler), "MyCallHandler");
        this.RegisterType(typeof(IMatchingRule), 
                       typeof(AnyMatchingRule), "AnyMatchingRule");

        this.RegisterType<IMyClass, MyClass>();
    }
    //apparently there is a new way to do this part
    // http://msdn.Microsoft.com/en-us/library/ff660911%28PandP.20%29.aspx

    public void SetupForInteception(Type t)
    {
        this.Configure<Interception>()
        .SetInterceptorFor(t, new InterfaceInterceptor())
        .AddPolicy("LoggingPolicy")
        .AddMatchingRule("AnyMatchingRule")
        .AddCallHandler("MyCallHandler");

    }
}
//THIS will match which methods to log.
public class AnyMatchingRule : IMatchingRule
{
    public bool Matches(MethodBase member)
    {
        return true;//this ends up loggin ALL methods.
    }
}
public class LogCallHandler : ICallHandler
{
    public IMethodReturn 
             Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
      //All method calls will result in a call here FIRST.
      //IMethodInvocation has an exception property which will let you know
      //if an exception occurred during the method call.
    }
 }
10
gideon

プロファイラーをトレースモードで使用します。次に、すべてが互いにどのように呼び出され、時間が費やされているかを確認します。商用プロファイラーの他に、無料のプロファイラーもあります。マネージコードには NP Profiler があり、非常に優れています。

さらに詳しく知りたい場合は、 Windows Performance Toolkit を使用できます。これにより、すべてのスレッドに関する完全な情報と、知りたい場合に相互にどのように相互作用するかがわかります。唯一の違いは、カーネルから管理対象フレームまでの範囲のスタックを取得することです。

これで十分でない場合は、トレースライブラリ(PostSharpを使用して自動的に...)を使用するか、手動で、または各ソースファイルのマクロを使用して、コードをインストルメント化できます。非常に高速で高度に構成可能な小さなトレースライブラリを作成しました。 こちら を参照してください。独自の機能として、スローされた例外を自動的にトレースできます。

private void SomeOtherMethod()
{
  using (Tracer t = new Tracer(myType, "SomeOtherMethod"))
  {
      FaultyMethod();
  }
}

private void FaultyMethod()
{
   throw new NotImplementedException("Hi this a fault");
}

ここに出力があります:

    18:57:46.665  03064/05180 <{{         > ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod  
    18:57:46.668  03064/05180 <{{         > ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod  
    18:57:46.670  03064/05180 <         }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod Exception thrown: System.NotImplementedException: Hi this a fault    
at ApiChange.IntegrationTests.Diagnostics.TracingTests.FaultyMethod()  
at ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod()  
at ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod()    
at ApiChange.IntegrationTests.Diagnostics.TracingTests.Demo_Show_Leaving_Trace_With_Exception() 

18:57:46.670  03064/05180 <         }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod Duration 2ms 18:57:46.689  03064/05180 <         }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod Duration 24ms
6
Alois Kraus

PostSharpは、属性で明示的に装飾することなく、複数のターゲットにアスペクトを適用する方法を確実に提供します。 マルチキャスト属性 を参照してください。

(マルチキャスト)アスペクトを開発するときは、その使用法を指定する必要があります。

[MulticastAttributeUsage(MulticastTargets.Method, TargetMemberAttributes = MulticastAttributes.Instance)]
[AttributeUsage(AttributeTargets.Assembly|AttributeTargets.Class|AttributeTargets.Method, AllowMultiple = true)]
[Serializable]
public class TraceAttribute : MethodInterceptionAspect
{
// Details skipped.
}

次に、ユースケースをカバーする方法でアスペクトを適用します(たとえば、AdventureWorks.BusinessLayer名前空間のすべてのパブリックメンバー)。

[Assembly: Trace( AttributeTargetTypes="AdventureWorks.BusinessLayer.*", AttributeTargetMemberAttributes = MulticastAttributes.Public )]
5
Goran