Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add a Trace() to every method call in C#?

Tags:

c#

logging

trace

I am having a hard time tracking down a lock issue, so I would like to log every method call's entry and exit. I've done this before with C++ without having to add code to every method. Is this possible with C#?

like image 425
Jon Tackabury Avatar asked Feb 17 '09 23:02

Jon Tackabury


People also ask

How do you trace a function in C++?

To define tracing functions in C++ programs, use the extern "C" linkage directive before your function definition. The function calls are only inserted into the function definition, and if a function is inlined, no tracing is done within the inlined code.

What does trace mean in C++?

The Fundamentals. The goal of tracing code in C++ is to write code that can emit desirable information at run-time. However, this should be done implicitly as much as possible. Meaning, tracing a particular function, should not be different than how a different function might be traced.


2 Answers

Probably your best bet would be to use an AOP (aspect oriented programming) framework to automatically call tracing code before and after a method execution. A popular choice for AOP and .NET is PostSharp.

like image 60
Dennis G. Avatar answered Oct 04 '22 01:10

Dennis G.


If your primary goal is to log function entry/exit points and occasional information in between, I've had good results with an Disposable logging object where the constructor traces the function entry, and Dispose() traces the exit. This allows calling code to simply wrap each method's code inside a single using statement. Methods are also provided for arbitrary logs in between. Here is a complete C# ETW event tracing class along with a function entry/exit wrapper:

using System; using System.Diagnostics; using System.Diagnostics.Tracing; using System.Reflection; using System.Runtime.CompilerServices;  namespace MyExample {     // This class traces function entry/exit     // Constructor is used to automatically log function entry.     // Dispose is used to automatically log function exit.     // use "using(FnTraceWrap x = new FnTraceWrap()){ function code }" pattern for function entry/exit tracing     public class FnTraceWrap : IDisposable     {         string methodName;         string className;          private bool _disposed = false;          public FnTraceWrap()         {             StackFrame frame;             MethodBase method;              frame = new StackFrame(1);             method = frame.GetMethod();             this.methodName = method.Name;             this.className = method.DeclaringType.Name;              MyEventSourceClass.Log.TraceEnter(this.className, this.methodName);         }          public void TraceMessage(string format, params object[] args)         {             string message = String.Format(format, args);             MyEventSourceClass.Log.TraceMessage(message);         }          public void Dispose()         {             if (!this._disposed)             {                 this._disposed = true;                 MyEventSourceClass.Log.TraceExit(this.className, this.methodName);             }         }     }      [EventSource(Name = "MyEventSource")]     sealed class MyEventSourceClass : EventSource     {         // Global singleton instance         public static MyEventSourceClass Log = new MyEventSourceClass();          private MyEventSourceClass()         {         }          [Event(1, Opcode = EventOpcode.Info, Level = EventLevel.Informational)]         public void TraceMessage(string message)         {             WriteEvent(1, message);         }          [Event(2, Message = "{0}({1}) - {2}: {3}", Opcode = EventOpcode.Info, Level = EventLevel.Informational)]         public void TraceCodeLine([CallerFilePath] string filePath = "",                                   [CallerLineNumber] int line = 0,                                   [CallerMemberName] string memberName = "", string message = "")         {             WriteEvent(2, filePath, line, memberName, message);         }          // Function-level entry and exit tracing         [Event(3, Message = "Entering {0}.{1}", Opcode = EventOpcode.Start, Level = EventLevel.Informational)]         public void TraceEnter(string className, string methodName)         {             WriteEvent(3, className, methodName);         }          [Event(4, Message = "Exiting {0}.{1}", Opcode = EventOpcode.Stop, Level = EventLevel.Informational)]         public void TraceExit(string className, string methodName)         {             WriteEvent(4, className, methodName);         }     } } 

Code that uses it will look something like this:

public void DoWork(string foo) {     using (FnTraceWrap fnTrace = new FnTraceWrap())     {         fnTrace.TraceMessage("Doing work on {0}.", foo);         /*         code ...         */     } } 
like image 25
Eric C. Berridge Avatar answered Oct 03 '22 23:10

Eric C. Berridge