Introduction
Tracing method calls to a log file is a troubleshooting technique used when a standard debug session is not possible (for example, when a given problem can only be reproduced in the production environment or in the customer's computer). When the method to be traced can be called in more than one context, simply logging the name and the parameters of such a method is not enough for understanding the application's workflow.
One option is to add tracing code to all methods which call the given method. An easier solution is tracing the current call stack. The StackFrame
and StackTrace
classes, belonging to the System.Diagnostics
namespace of the .NET Framework, can be used for this purpose.
How to use StackFrame and StackTrace
The StackFrame
class (see the online MSDN library) represents a method call on the current call stack. The StackTrace
class (see the online MSDN library) is a collection of StackFrame
objects. Therefore, by means of the StackTrace
constructor, a snapshot of the current call stack can be created.
Moreover, the StackTrace.ToString
method returns a string representation:
public static class Logger
{
...
public static string CurrentStackDefaultLog()
{
var l_CurrentStack = new System.Diagnostics.StackTrace(true);
return l_CurrentStack.ToString();
}
...
}
An example of its output follows (that is similar to the output of the Exception.ToString
method):
at Mazzeranghi.StackLogger.Logger.CurrentStackDefaultLog()
in C:\VS2010Express\Projects\Mazzeranghi.StackLogger\Logger.cs:line 54
at Mazzeranghi.StackLogger.Logger.AddCurrentStackDefaultLog()
in C:\VS2010Express\Projects\Mazzeranghi.StackLogger\Logger.cs:line 48
at Mazzeranghi.StackLogger.BankAccount.Withdraw(Int32 p_WithdrawalValue)
in C:\VS2010Express\Projects\Mazzeranghi.StackLogger\BankAccount.cs:line 39
at Mazzeranghi.StackLogger.MainFrame.ValidOperationWithDefaultLog_Click(Object p_Sender,
EventArgs p_EventArgs)
in C:\VS2010Express\Projects\Mazzeranghi.StackLogger\MainFrame.cs:line 41
at System.Windows.Forms.Control.OnClick(EventArgs e)
...
But, if you want to customize such a string representation (for instance, in order to remove the lines corresponding to Logger
methods), several methods of the StackFrame
class are available:
public static class Logger
{
...
public static String CurrentStackCustomizedLog()
{
var l_StackLog = new System.Text.StringBuilder();
var l_CurrentStack = new System.Diagnostics.StackTrace(true);
for (Int32 x = 0; x < l_CurrentStack.FrameCount; ++x)
{
var l_MethodCall = l_CurrentStack.GetFrame(x);
if (IsMethodToBeIncluded(l_MethodCall))
l_StackLog.AppendLine(MethodCallLog(l_MethodCall));
}
return l_StackLog.ToString();
}
private static bool IsMethodToBeIncluded(
System.Diagnostics.StackFrame p_StackMethod)
{
var l_Method = p_StackMethod.GetMethod();
if (l_Method.DeclaringType == typeof(Logger))
return false;
else
return true;
}
private static String MethodCallLog(System.Diagnostics.StackFrame p_MethodCall)
{
System.Text.StringBuilder l_MethodCallLog =
new System.Text.StringBuilder();
var l_Method = p_MethodCall.GetMethod();
l_MethodCallLog.Append(l_Method.DeclaringType.ToString());
l_MethodCallLog.Append(".");
l_MethodCallLog.Append(p_MethodCall.GetMethod().Name);
var l_MethodParameters = l_Method.GetParameters();
l_MethodCallLog.Append("(");
for (Int32 x = 0; x < l_MethodParameters.Length; ++x)
{
if (x > 0)
l_MethodCallLog.Append(", ");
var l_MethodParameter = l_MethodParameters[x];
l_MethodCallLog.Append(l_MethodParameter.ParameterType.Name);
l_MethodCallLog.Append(" ");
l_MethodCallLog.Append(l_MethodParameter.Name);
}
l_MethodCallLog.Append(")");
var l_SourceFileName = p_MethodCall.GetFileName();
if (!String.IsNullOrEmpty(l_SourceFileName))
{
l_MethodCallLog.Append(" in ");
l_MethodCallLog.Append(l_SourceFileName);
l_MethodCallLog.Append(": line ");
l_MethodCallLog.Append(p_MethodCall.GetFileLineNumber().ToString());
}
return l_MethodCallLog.ToString();
}
...
}
An output example follows:
Mazzeranghi.StackLogger.BankAccount.Deposit(Int32 p_DepositValue)
in C:\VS2010Express\Projects\Mazzeranghi.StackLogger\BankAccount.cs: line 31
Mazzeranghi.StackLogger.MainFrame.ValidOperationWithCustomizedLog_Click(Object p_Sender,
EventArgs p_EventArgs)
in C:\VS2010Express\Projects\Mazzeranghi.StackLogger\MainFrame.cs: line 48
System.Windows.Forms.Control.OnClick(EventArgs e)
...
Sample code
A sample C# application is also available for testing the following cases:
Exception.ToString
log (see button "Invalid Operation").StackTrace
default log (see button "Valid Operation (with default log)").StackTrace
customized log (see button "Valid Operation (with customized log)").
