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

后端 未结 6 1591
忘掉有多难
忘掉有多难 2020-11-28 11:47

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

6条回答
  •  感动是毒
    2020-11-28 12:31

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

提交回复
热议问题