【问题标题】:How to trace every method called如何跟踪每个调用的方法
【发布时间】:2021-08-07 22:40:50
【问题描述】:

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

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

还有其他方法可以让我快速追踪所有拨打的电话吗?

【问题讨论】:

  • 我不禁想知道你为什么想要那个。如果出现异常,您可以查看堆栈跟踪。但是为什么你想要所有方法调用的日志呢?
  • 有一个错误,我们可以追踪到某个点,然后控制转到不是我们的应用程序的父应用程序 - 所以没有源代码(在此之后应用程序停止响应)。为了找出在我们的应用程序中调用了什么,我们正在尝试这个。

标签: c# logging trace


【解决方案1】:

您可以通过Unity Interception 做到这一点

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

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

  1. 制作一个包含MyClass中所有方法的接口=>IMyClass
  2. 您可以设置 InterfaceInterception(就像我在下面所做的那样)或者您可以通过其他一些方式来设置它。见here for all options
  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.
    }
 }

【讨论】:

  • 我认为他正在尝试在不为每个方法/类添加属性的情况下做到这一点(这与示例不同)
  • 听起来好像需要你为每个类创建一个接口;在我看来,这比属性更有用。
  • @BrianBall 是的,这是真的。但是,如果您打算使用依赖注入(这是一件好事),那么这是一个不错的选择。
  • 这种技术再好,对我来说却毫无用处。我不能修改 1000 个或更多类。
  • @ShaQ.Blogs 啊太糟糕了!!我发布它是因为我做了几个月的认真研究并为我的公司实施了这个。在我的搜索中,我没有找到任何其他方法(除了购买一个为您执行此操作的精美库之一)
【解决方案2】:

在跟踪模式下使用 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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-05
      • 2012-12-07
      • 2011-03-22
      • 1970-01-01
      • 2012-01-10
      • 1970-01-01
      相关资源
      最近更新 更多