web-dev-qa-db-fra.com

Comment tracer chaque méthode appelée

J'ai un projet existant où je voudrais découvrir tous les appels en cours et peut-être les vider dans un fichier journal.

J'ai jeté un coup d'œil à ce fil , mais n'a pas beaucoup aidé. J'ai essayé PostSharp, et l'exemple montre comment y parvenir. Mais je dois ajouter un attribut à chaque méthode sacrément. Être un projet existant, avec de nombreuses méthodes qui n'est pas une option réalisable.

Existe-t-il un autre moyen par lequel je peux retracer rapidement tous les appels effectués?

26
ShaQ.Blogs

Vous pouvez le faire avec nity Interception

Voir ceci article pour un exemple . L'article utilise des attributs, mais mon exemple de code ci-dessous utilise le système d'injection de dépendance (codage vers une interface) pour configurer l'interception.

Si vous voulez vous connecter MyClass, cela ressemble à ceci:

  1. Créer une interface contenant toutes les méthodes dans MyClass => IMyClass
  2. Vous configurez InterfaceInterception (comme je l'ai fait ci-dessous) OR il y a plusieurs autres façons de le configurer. Voir ici pour toutes les options .
  3. Vous allez configurer une stratégie pour intercepter toutes les méthodes qui correspondent à IMatchingRule.
  4. Tous les appels seront désormais interceptés par votre implémentation ICallHandler .

Code:

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

Utilisez un profileur en mode de traçage. Ensuite, vous verrez comment tout s'appelle et où le temps est passé. Outre les profileurs commerciaux, il existe également des profils gratuits. Pour le code managé, il y a NP Profiler qui est assez bon.

Si vous voulez aller plus loin, vous pouvez utiliser Windows Performance Toolkit qui vous donne des informations complètes sur tous les threads et comment interagir les uns avec les autres si vous voulez le savoir. La seule différence est que vous obtenez des piles allant du noyau jusqu'à vos trames gérées.

Si cela ne suffit pas, vous pouvez instrumenter votre code avec une bibliothèque de suivi (soit automatiquement avec PostSharp, ....) soit manuellement ou avec une macro pour chaque fichier source. J'ai créé une petite bibliothèque de traçage qui est assez rapide et hautement configurable. Voir ici . En tant que fonctionnalité unique, il peut suivre automatiquement toute exception levée.

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

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

Voici la sortie:

    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 offre certainement un moyen d'appliquer un aspect à plusieurs cibles sans les décorer explicitement d'attributs. Voir Attributs de multidiffusion .

Lors du développement d'un aspect (multicast), vous devez spécifier son utilisation:

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

Et appliquez ensuite l'aspect d'une manière qui couvre votre cas d'utilisation (par exemple, tous les membres publics dans l'espace de noms AdventureWorks.BusinessLayer):

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