When logging in C#, how can I learn the name of the method that called the current method? I know all about System.Reflection.MethodBase.GetCurrentMethod(), but I want to go one step beneath this in the stack trace. I've considered parsing the stack trace, but I am hoping to find a cleaner more explicit way, something like Assembly.GetCallingAssembly() but for methods.
Try this:
using System.Diagnostics;
// Get call stack
StackTrace stackTrace = new StackTrace();
// Get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
one-liner:
(new System.Diagnostics.StackTrace()).GetFrame(1).GetMethod().Name
It is from Get Calling Method using Reflection [C#].
In C# 5, you can get that information using caller info:
//using System.Runtime.CompilerServices;
public void SendError(string Message, [CallerMemberName] string callerName = "")
{
Console.WriteLine(callerName + "called me.");
}
You can also get the [CallerFilePath] and [CallerLineNumber].
You can use Caller Information and optional parameters:
public static string WhoseThere([CallerMemberName] string memberName = "")
{
return memberName;
}
This test illustrates this:
[Test]
public void Should_get_name_of_calling_method()
{
var methodName = CachingHelpers.WhoseThere();
Assert.That(methodName, Is.EqualTo("Should_get_name_of_calling_method"));
}
While the StackTrace works quite fast above and would not be a performance issue in most cases the Caller Information is much faster still. In a sample of 1000 iterations, I clocked it as 40 times faster.
A quick recap of the 2 approaches with speed comparison being the important part.
http://geekswithblogs.net/BlackRabbitCoder/archive/2013/07/25/c.net-little-wonders-getting-caller-information.aspx
Determining the caller at compile-time
static void Log(object message,
[CallerMemberName] string memberName = "",
[CallerFilePath] string fileName = "",
[CallerLineNumber] int lineNumber = 0)
{
// we'll just use a simple Console write for now
Console.WriteLine("{0}({1}):{2} - {3}", fileName, lineNumber, memberName, message);
}
Determining the caller using the stack
static void Log(object message)
{
// frame 1, true for source info
StackFrame frame = new StackFrame(1, true);
var method = frame.GetMethod();
var fileName = frame.GetFileName();
var lineNumber = frame.GetFileLineNumber();
// we'll just use a simple Console write for now
Console.WriteLine("{0}({1}):{2} - {3}", fileName, lineNumber, method.Name, message);
}
Comparison of the 2 approaches
Time for 1,000,000 iterations with Attributes: 196 ms
Time for 1,000,000 iterations with StackTrace: 5096 ms
So you see, using the attributes is much, much faster! Nearly 25x
faster in fact.
We can improve on Mr Assad's code (the current accepted answer) just a little bit by instantiating only the frame we actually need rather than the entire stack:
new StackFrame(1).GetMethod().Name;
This might perform a little better, though in all likelihood it still has to use the full stack to create that single frame. Also, it still has the same caveats that Alex Lyman pointed out (optimizer/native code might corrupt the results). Finally, you might want to check to be sure that new StackFrame(1) or .GetFrame(1) don't return null, as unlikely as that possibility might seem.
See this related question:
Can you use reflection to find the name of the currently executing method?
In general, you can use the System.Diagnostics.StackTrace class to get a System.Diagnostics.StackFrame, and then use the GetMethod() method to get a System.Reflection.MethodBase object. However, there are some caveats to this approach:
It represents the runtime stack -- optimizations could inline a method, and you will not see that method in the stack trace.
It will not show any native frames, so if there's even a chance your method is being called by a native method, this will not work, and there is in-fact no currently available way to do it.
(NOTE: I am just expanding on the answer provided by Firas Assad.)
As of .NET 4.5 you can use Caller Information Attributes:
CallerFilePath - The source file that called the function;
CallerLineNumber - Line of code that called the function;
CallerMemberName - Member that called the function.
public void WriteLine(
[CallerFilePath] string callerFilePath = "",
[CallerLineNumber] long callerLineNumber = 0,
[CallerMemberName] string callerMember= "")
{
Debug.WriteLine(
"Caller File Path: {0}, Caller Line Number: {1}, Caller Member: {2}",
callerFilePath,
callerLineNumber,
callerMember);
}
This facility is also present in ".NET Core" and ".NET Standard".
References
Microsoft - Caller Information (C#)
Microsoft - CallerFilePathAttribute Class
Microsoft - CallerLineNumberAttribute Class
Microsoft - CallerMemberNameAttribute Class
Obviously this is a late answer, but I have a better option if you can use .NET 4.5 or newer:
internal static void WriteInformation<T>(string text, [CallerMemberName]string method = "")
{
Console.WriteLine(DateTime.Now.ToString() + " => " + typeof(T).FullName + "." + method + ": " + text);
}
This will print the current Date and Time, followed by "Namespace.ClassName.MethodName" and ending with ": text".
Sample output:
6/17/2016 12:41:49 PM => WpfApplication.MainWindow..ctor: MainWindow initialized
Sample use:
Logger.WriteInformation<MainWindow>("MainWindow initialized");
Note that doing so will be unreliable in release code, due to optimization. Additionally, running the application in sandbox mode (network share) won't allow you to grab the stack frame at all.
Consider aspect-oriented programming (AOP), like PostSharp, which instead of being called from your code, modifies your code, and thus knows where it is at all times.
/// <summary>
/// Returns the call that occurred just before the "GetCallingMethod".
/// </summary>
public static string GetCallingMethod()
{
return GetCallingMethod("GetCallingMethod");
}
/// <summary>
/// Returns the call that occurred just before the the method specified.
/// </summary>
/// <param name="MethodAfter">The named method to see what happened just before it was called. (case sensitive)</param>
/// <returns>The method name.</returns>
public static string GetCallingMethod(string MethodAfter)
{
string str = "";
try
{
StackTrace st = new StackTrace();
StackFrame[] frames = st.GetFrames();
for (int i = 0; i < st.FrameCount - 1; i++)
{
if (frames[i].GetMethod().Name.Equals(MethodAfter))
{
if (!frames[i + 1].GetMethod().Name.Equals(MethodAfter)) // ignores overloaded methods.
{
str = frames[i + 1].GetMethod().ReflectedType.FullName + "." + frames[i + 1].GetMethod().Name;
break;
}
}
}
}
catch (Exception) { ; }
return str;
}
Maybe you are looking for something like this:
StackFrame frame = new StackFrame(1);
frame.GetMethod().Name; //Gets the current method name
MethodBase method = frame.GetMethod();
method.DeclaringType.Name //Gets the current class name
private static MethodBase GetCallingMethod()
{
return new StackFrame(2, false).GetMethod();
}
private static Type GetCallingType()
{
return new StackFrame(2, false).GetMethod().DeclaringType;
}
A fantastic class is here: http://www.csharp411.com/c-get-calling-method/
Another approach I have used is to add a parameter to the method in question. For example, instead of void Foo(), use void Foo(string context). Then pass in some unique string that indicates the calling context.
If you only need the caller/context for development, you can remove the param before shipping.
For getting Method Name and Class Name try this:
public static void Call()
{
StackTrace stackTrace = new StackTrace();
var methodName = stackTrace.GetFrame(1).GetMethod();
var className = methodName.DeclaringType.Name.ToString();
Console.WriteLine(methodName.Name + "*****" + className );
}
Extra information to Firas Assaad answer.
I have used new StackFrame(1).GetMethod().Name; in .net core 2.1 with dependency injection and I am getting calling method as 'Start'.
I tried with [System.Runtime.CompilerServices.CallerMemberName] string callerName = ""
and it gives me correct calling method
We can also use lambda's in order to find the caller.
Suppose you have a method defined by you:
public void MethodA()
{
/*
* Method code here
*/
}
and you want to find it's caller.
1. Change the method signature so we have a parameter of type Action (Func will also work):
public void MethodA(Action helperAction)
{
/*
* Method code here
*/
}
2. Lambda names are not generated randomly. The rule seems to be: > <CallerMethodName>__X
where CallerMethodName is replaced by the previous function and X is an index.
private MethodInfo GetCallingMethodInfo(string funcName)
{
return GetType().GetMethod(
funcName.Substring(1,
funcName.IndexOf(">", 1, StringComparison.Ordinal) - 1)
);
}
3. When we call MethodA the Action/Func parameter has to be generated by the caller method.
Example:
MethodA(() => {});
4. Inside MethodA we can now call the helper function defined above and find the MethodInfo of the caller method.
Example:
MethodInfo callingMethodInfo = GetCallingMethodInfo(serverCall.Method.Name);
StackFrame caller = (new System.Diagnostics.StackTrace()).GetFrame(1);
string methodName = caller.GetMethod().Name;
will be enough, I think.
Related
I want to write a very simple logging method. It will basically wrap WriteLine(...). It should take any number of parameters. The first will either be a StreamWriter object or null. If the first object is null then it should use Console.Writeline()... otherwise the StreamWriter object.
I have seen that I should perhaps be using the params ... method parameter keyword, à la:
private static void MyLog(params object[] list) {
if (list.Length <= 0) {
throw new ArgumentException("Parameter list is empty.");
}
if (list.Length <= 2)
{
throw new ArgumentException("Parameter list is too short.");
}
var log = (StreamWriter) list[0];
if (log != null) {
log.WriteLine(list.Skip(1).Take(list.Length - 1));
} else {
Console.WriteLine(list.Skip(1).Take(list.Length - 1));
}
}
This is called as:
try {
var exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
var dirPath = Path.GetDirectoryName(exePath);
var logFile = dirPath + "\\myLog.log";
_log = File.AppendText(logFile);
_log.AutoFlush = true;
MyLog(_log, "----- START ----- {0:yyyy-MM-dd HH:mm:ss} -----", DateTime.Now);
} catch (Exception e) {
_log = null;
MyLog(null, e.Message);
}
...
MyLog(_log, "{0}:AD property {1} is null", username, property);
...
I was really hoping that the list.Skip(1).Take(list.Length - 1) construct would do an "array slice" and feed the 1..nth list objects to WriteLine and that it would do the right thing. Instead I get a stream of
System.Linq.Enumerable+<TakeIterator>d__25`1[System.Object]
How does one correctly wrap Writeline for such things?
Is there a better way to handle this sort of string interpolation logging to file or console?
The general idea for what you want already exists in the framework, albeit with a somewhat different API.
Take a look at the System.Diagnostics.Trace type. It has a WriteLine() method, and it works by letting you attach one or more TraceListener objects, of which the framework provides ConsoleTraceListener and TextWriterTraceListener (for files) out of the box, as well as others.
You can also make your own TraceListener to do things like log to a database or re-implement existing listeners to add features like automatically including timestamp or path information.
Sadly, Trace.WriteLine() is missing some of the expected overloads. This was more of problem until recently, but now that we have interpolated strings it's no big deal.
In this case, you would build your own TraceListener type (inherit from TextWriterTraceListener and most of the work is done for you) which attempts to append to a log file, but writes to the Console if an exception is thrown. Later on, the code just looks like this, and you get all of the features you wanted:
Trace.WriteLine($"{username}:AD property {property} is null");
At very least, it's much better practice to provide overloads to decide whether to use a streamwriter or console, like this:
private static void MyLog(string format, params object[] list)
{
Console.WriteLine(format, list);
}
private static void MyLog(StreamWriter log, string format, params object[] list)
{
log.WriteLine(format, list);
}
Again, that is MUCH better practice. But if you really want your existing code, replace the Take() calls with ToArray(). Then you match up with what the existing WriteLine() overloads expect.
private static void MyLog(StreamWriter sw, string format, params object[] args)
{
if (sw == null)
Console.WriteLine(format, args);
else
sw.WriteLine(format, args);
}
If you know that your first parameter is a StreamWriter, change the signature to reflect that:
private static void MyLog(StreamWriter log, params object[] list) {
If you know the what type the rest of the objects are, I'd type them too.
The number of elements in list will never be less than 0:
if (list.Length <= 0) {
The Take method is only needed if you want a subset of elements from the beginning, not the rest of them, and since you already skipped one, you just want the rest:
list.Skip(1)
The above, however, is not necessary, since we changed the signature of your method, so you just want your full list array.
The WriteLine method doesn't know how you want the array of unknown objects formatted. Even if it was a string[], I'm not sure it would know what to do with it. If we assume that it's a string[], you could do the following:
WriteLine(list.Aggregate((current, next) => current + Environment.NewLine + next))
If that doesn't help, please specify which content you expect, and how you'd like it formatted.
This question already has answers here:
How can I find the method that called the current method?
(17 answers)
Closed 6 years ago.
Is it possible to determine the calling method name "Eat Pizza" in PostError?
I guess I could pass "EatPizza" as one of the arguments, but that would require changes each time the method name changes (unnecessary maintenance). But then, I wasn't even able to find the method name "EatPizza" in the context of "EatPizza" (using stacktrace, getframe, getmethod).
public void EatPizza(Pizza p){
if(p==null){ //A arbitrary made up error
Utilities.PostError();
}
else{
p.Slices -= 1;
}
}
...
public void PostError(){
//Basically posting to database the name of the method
//Tried this, didn't work: (new StackTrace(true)).GetFrame(5).GetMethod().Name
//Is it possible to determine the calling method name "Eat Pizza" in this context?
}
When I try different values (0 to StackTrace.FrameCount-1) in StackTrace.GetFrame, I get the following values, when I just want "EatPizza":
.ctor
ThreadStart
Main
_nExecuteAssembly
RunUsersAssemblyDebugInZone
You were on the right track with creating a StackTrace object, but you seem to have misunderstood the argument to GetFrame. Frames are numbered from the bottom-most frame, so:
GetFrame(0) would return PostError
GetFrame(1) would return the caller of PostError
So just try this:
var trace = new StackTrace(true);
WriteToDB(trace.GetFrame(1).GetMethod().Name);
Personally, I would prefer to get the entire stack trace rather than just the caller, so I'd do this:
var trace = new StackTrace(true);
WriteToDB(trace.ToString());
Is it possible to determine the calling method name "Eat Pizza" in PostError? I guess I could pass "EatPizza" as one of the arguments, but that would require changes each time the method name changes (unnecessary maintenance).
Calling PostError in all the methods in which something could go wrong is also "unnecessary maintenance". It also complicates the execution flow of your program, because you will have to check for errors all over the place, and high-level processes will have to check if the low level processes completed successfully.
It is better to use the exception handling structures provided by the CLR and C#.
The exact location in which the error occured is stored in the exception's StackTrace property.
pubic void BigDinnerEatingProcess()
{
try
{
WhateverHappensAtTheTopLevel();
}
catch (PizzaNotDeliveredException ex)
{
Utilities.PostError(ex);
MessageBox.Show("Dinner was not eaten. Please make sure the pizza is delivered.");
}
}
public void EatPizza(Pizza p)
{
if (p == null)
throw new PizzaNotDeliveredException();
p.RemoveOneSlice();
}
private void PostError(Exception ex)
{
string errorLocation = ex.StackTrace;
//...
}
I am looking into C# logging and I do not want my log messages to spend any time processing if the message is below the logging threshold. The best I can see log4net does is a threshold check AFTER evaluating the log parameters.
Example:
_logger.Debug( "My complicated log message " + thisFunctionTakesALongTime() + " will take a long time" )
Even if the threshold is above Debug, thisFunctionTakesALongTime will still be evaluated.
In log4net you are supposed to use _logger.isDebugEnabled so you end up with
if( _logger.isDebugEnabled )
_logger.Debug( "Much faster" )
I want to know if there is a better solution for .net logging that does not involve a check each time I want to log.
In C++ I am allowed to do
LOG_DEBUG( "My complicated log message " + thisFunctionTakesALongTime() + " will take no time" )
since my LOG_DEBUG macro does the log level check itself. This frees me to have a 1 line log message throughout my app which I greatly prefer. Anyone know of a way to replicate this behavior in C#?
If you can target .NET 3.5 (C# 3.0) you can use extension methods to wrap the if statements.
so you can do the equivalent "macro":
logger.Log_Debug("Much faster");
logger.Log_Debug(() => { "My complicated log message " + thisFunctionTakesALongTime() + " will take no time" });
by wrapping the check in this method:
public class Log4NetExtensionMethods {
// simple string wrapper
public void Log_Debug(this log4net.ILog logger, string logMessage) {
if(logger.isDebugEnabled) {
logger.Debug(logMessage);
}
}
// this takes a delegate so you can delay execution
// of a function call until you've determined it's necessary
public void Log_Debug(this log4net.ILog logger, Func<string> logMessageDelegate) {
if(logger.isDebugEnabled) {
logger.Debug(logMessageDelegate());
}
}
}
17.4.2 The Conditional attribute
The attribute Conditional enables the definition of conditional methods. The Conditional attribute indicates a condition by testing a conditional compilation symbol. Calls to a conditional method are either included or omitted depending on whether this symbol is defined at the point of the call. If the symbol is defined, the call is included; otherwise, the call (including evaluation of the parameters of the call) is omitted.
[ Conditional("DEBUG") ]
public static void LogLine(string msg,string detail)
{
Console.WriteLine("Log: {0} = {1}",msg,detail);
}
public static void Main(string[] args)
{
int Total = 0;
for(int Lp = 1; Lp < 10; Lp++)
{
LogLine("Total",Total.ToString());
Total = Total + Lp;
}
}
The problem here is that all method parameters must be evaluated before the method is invoked. There is no way around this, given the syntax you are using. Since C# does not have a real preprocessor or macros, you can't do anything like "LOG_DEBUG". The best you could do is use if (logger.isDebugEnable) as suggested.
The only thing I can think of is maybe using something like a lambda expression to delay evaluation. But I would warn you that this will almost certainly have more of a performance hit in the end.
internal class Sample
{
private static void Main(string[] args)
{
DelayedEvaluationLogger.Debug(logger, () => "This is " + Expensive() + " to log.");
}
private static string Expensive()
{
// ...
}
}
internal static class DelayedEvaluationLogger
{
public static void Debug(ILog logger, Func<string> logString)
{
if (logger.isDebugEnabled)
{
logger.Debug(logString());
}
}
}
Without a preprocessor you're SOL. Of course there's nothing preventing you from using one before feeding your code to the C# compiler.
Is there any way in C# to pass a random method as a parameter?
To explain my question:
I want to write a simple Logger-Tool that reports the entering and leaving of a method with the passed arguments an the class and method name:
The log file I'm aiming at:
ENTERING: ClassOfDoom::MethodOfDoom( arg1={1} [int], arg2={true} [bool] )
LEAVING: ClassOfDoom::MethodOfDoom RETURNING 1 [int]
The code I have in mind:
class ClassOfDoom {
// Remeber: MethodOfDoom is a _random_ method with _random_ arguments
public int MethodOfDoom(int arg1, bool arg2) {
Log.Entering(this, this.MethodOfDoom, arg1, arg2);
...
return Log.Returing(this, this.MethodOfDoom, 1);
}
}
Is there a way to achieve this? Or isn't C# as flexible as that?
Thanks in advance!
You can make your logging function take a MethodBase argument and use MethodBase.GetCurrentMethod to pass the current method info as an argument.
Then, in the logger, you could check its properties Name and DeclaringType to get the method information. Also, passing parameters is easy by declaring a params object[] args parameter in the logging function:
public static void Entering(object obj, MethodBase methodInfo,
params object[] args) {
Console.WriteLine("ENTERING {0}:{1}", methodInfo.DeclaringType.Name,
methodInfo.Name);
...
}
I'm not sure I entirely understand your question, but if you are trying to make a call to Log.Entering and Log.Returning inside an arbitrary (random) method and using the method's actual parameters, you should check out PostSharp. It will allow you to inject code in a method body and then do some work based on the reflected method information you get from the .NET framework (and the actual parameters passed to the method at runtime).
You could do it with Expression easily enough - it would look something like:
Log.Capture(() => this.MethodOfDoom(arg1, arg2));
Here's an example; I've been a bit lazy using Compile().DynamicInvoke() to read the arg-values - for real code I'd try to read it more directly:
using System;
using System.Diagnostics;
using System.Linq.Expressions;
class Program
{
DateTime MethodOfDoom(string s, int i)
{
return DateTime.Today;
}
public void RunTest()
{
int i =123;
Log.Capture(() => this.MethodOfDoom("abc", i));
}
static void Main()
{
new Program().RunTest();
}
}
static class Log
{
public static T Capture<T>(Expression<Func<T>> method)
{
MethodCallExpression mce = method.Body as MethodCallExpression;
if (mce == null) throw new InvalidOperationException(
"Method-call expected");
string name = mce.Method.Name;
try
{
int i = 0;
foreach(var param in mce.Method.GetParameters())
{
object argValue = Expression.Lambda(mce.Arguments[i++])
.Compile().DynamicInvoke();
Trace.WriteLine(param.Name + "=" + argValue, name);
}
Trace.WriteLine("ENTERING", name);
T result = method.Compile().Invoke();
Trace.WriteLine("EXITING: " + result, name);
return result;
}
catch (Exception ex)
{
Trace.WriteLine("EXCEPTION: " + ex, name);
throw;
}
}
}
If widely used in your code, this scenario is best implemented using Aspect Oriented Programming (AOP) techniques. There are different frameworks that can be used (such as Spring.NET AOP), which you can use in your .NET application. Here is a reference article that might help you get started:
http://www.developer.com/lang/article.php/10924_3795031_2
The referenced article gives you the logging enter/exit scenario as an example.
I have used PostSharp to do this very thing before.
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#?
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.
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 ...
*/
}
}
A profiler is great for looking at your running code during development but if you're looking for the ability to do custom traces in production, then, as Denis G. mentionned, PostSharp is the perfect tool: you don't have to change all your code and you can easily switch it on/off.
It's also easy to set-up in a few minutes and Gaël Fraiteur, the creator of PostSharp even has videos that shows you how easy it is to add tracing to an existing app.
You will find examples and tutorials in the documentation section.
Use ANTS Profiler from Red Gate would be your best bet. Failing that, look into interceptors in Castle Windsor. That does assume you're loading your types via IoC though.
Reflection is another way, you can use the System.Reflection.Emit methods to "write" code into memory. That code could replace your method's code, and execute it but with appropriate logging. Good luck on that one, though... Easier would be to use an Aspect Oriented Programming framework like Aspect#.
It might be waiting for the lock issue to take hold, doing a memory dump and analysing the call stack on various threads. You can use DebugDiag or the adplus script (hang mode, in this case) that comes with Debugging Tools for Windows.
Tess Ferrandez also has an excellent lab series on learning to debug various issues using .NET memory dumps. I highly recommend it.
How do you know that it's happening? If this is a multithreaded application, i would recommend testing for the condition and calling System.Diagnostics.Debugger.Break() at runtime when it's detected. Then, simply open up the Threads window and step through the call stacks on each relevant thread.