如何跟踪每个调用的方法

时间:2013-02-13 20:37:40

标签: c# logging trace

我有一个现有项目,我想查找所有正在进行的调用,并可能转储到日志文件中。

我看了at this thread,但没多大帮助。 我试过PostSharp,这个例子展示了如何实现它。但我需要为每个darn方法添加一个属性。作为一个现有的项目,有许多方法是不可行的选择。

有没有其他方法可以快速追踪所有来电?

3 个答案:

答案 0 :(得分:10)

您可以使用Unity Interception

执行此操作

article for a sample。本文使用属性,但下面的代码示例使用依赖注入系统(编码到接口)来设置拦截。

如果你想记录MyClass,它会是这样的:

  1. 制作一个包含MyClass =>中所有方法的界面IMyClass
  2. 您设置了InterfaceInterception(就像我在下面所做的那样)或者还有其他一些方法可以设置它。见here for all options
  3. 您将设置策略以拦截与IMatchingRule匹配的所有方法。
  4. 现在,ICallHandler实施将拦截所有来电。
  5. 代码:

    //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.
        }
     }
    

答案 1 :(得分:5)

在跟踪模式下使用Profiler。然后你会看到一切都是如何相互呼唤以及花费的时间。除商业剖析外,还有免费的。 对于托管代码,NP Profiler非常好。

如果你想深入一点,你可以使用Windows Performance Toolkit,它可以为你提供所有线程的完整信息,以及如果你想知道如何互相交流。唯一的区别是你得到的堆栈范围从内核到托管框架。

如果这还不够,您可以使用跟踪库(自动使用PostSharp,......)或手动或使用宏来为每个源文件检测代码。 我创建了一个非常快速且高度可配置的跟踪库。见here。作为独特功能,它可以自动跟踪任何抛出的异常。

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

答案 2 :(得分:5)

PostSharp肯定提供了一种方法,可以将一个方面应用于多个目标,而无需明确地使用属性进行修饰。请参阅Multicast attributes

开发(多播)方面时,必须指定其用法:

[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 )]