Playing .NET Doctor: Diagnose Application Hiccups with .NET Classes
This month's .NET Nuts & Bolts covers the different .NET Framework options for diagnosing issues within your applications. It touches on a couple of the classes available in the System.Diagnostics namespace and the functionality they provide for debugging and tracking an application's execution path.
Classic Debugging
Modern Day Debugging
System.Diagnostics.Debug Sample Code
The following are some of the more common methods available in the Debug class:
- Assert—Displays a dialog message if the condition being checked is false
- Write/WriteLine—Writes information with or without a new line
- WriteIf/WriteLineIf—Conditionally writes information with or without a new line
- Indent/Unindent—Indents or unindents the debugging output
System.Diagnostics.Debug.Assert(false, "Message",
"Detail message to show in the debug window.");
Random rand = new Random(100);
System.Diagnostics.Debug.Indent();
System.Diagnostics.Debug.WriteLine("First random numbeCr: "
+ rand.Next().ToString());
System.Diagnostics.Debug.Unindent();
System.Diagnostics.Debug.WriteLineIf(rand.Next()%2 == 0,
"Even random number generated.");
Figure 2: Debug Output
Using a Configuration File
Another handy System.Diagnostics.Debug option is the ability to control the Debug class through the application's configuration file (web.config or app.config). A <system.diagnostics> element allows control of the behavior. The following example sets the size of indentions when printing and controls whether or not the Assert method generates a dialog:
<system.diagnostics>
<trace autoflush="true" indentsize="7" />
<assert assertuienabled="false" />
</system.diagnostics>
When you add the items above to your configuration file and execute it, you see slightly different output. Instead of the dialog from Figure 2, the output displays larger indention than the default (see Figure 3).
Figure 3: Control Debug Through Configuration
Tracing
The System.Diagnostics.Trace class provides a set of methods and properties for tracing the execution of code. These statements are often handy when you deal with complex logic and aren't sure where the code is at in execution. Trace statements are very similar to Debug statements. Trace exposes the same methods and functionality as the Debug class offers. The difference is that Trace is enabled by default for both debug and release builds. Thus, Trace statements can be used to trace the execution of code when it has been released to production. This can be handy for finding additional information on how your application is behaving in production.
System.Diagnostics.Trace Sample Code
Because the Debug and Trace classes have the same methods, I just changed the sample code above to use Trace instead of debug. The output will be the same, so I won't bother to include the figures again:
System.Diagnostics.Trace.Assert(false, "Message",
"Detail message to show in the debug window.");
Random rand = new Random(100);
System.Diagnostics.Trace.WriteLine("First random number: " +
rand.Next().ToString());
System.Diagnostics.Trace.Indent();
System.Diagnostics.Trace.WriteLineIf(rand.Next()%2 == 0,
"Even random number generated.");
System.Diagnostics.Trace.Unindent();
Listeners
The previous examples are all well and good as long as you're running the code in Visual Studio so that you can see the output window. This may work when debugging on the local machine, but it won't be an option when the application is in production. Thus, you need to be able to control where the output from Debug and Trace statements is written. This is done through what is known as a listener. A listener does just as its name implies: It listens for debug or trace output and then behaves accordingly. You can use a TextWriterTraceListener class to write Debug or Trace output to a TextWriter or a Stream, which can result in output being written to the console, a file, and so forth. You also can use an EventLogTraceListener to send messages to the Windows Event Log. Finally, you have an abstract TraceListener class that you can implement to create custom listeners for monitoring debug and trace output.
Listener Sample Code
The following sample code extends the previously given example code to have the output written to the console window rather than the Output window of the debugger (see Figure 4). It also demonstrates how to send the output just to the console:
// Add a listener to send output to the console
System.Diagnostics.TextWriterTraceListener writer = new
System.Diagnostics.TextWriterTraceListener(System.Console.Out);
System.Diagnostics.Debug.Listeners.Add(writer);
// Remove the default listener and only send to the console
System.Diagnostics.Debug.Listeners.Remove(
System.Diagnostics.Debug.Listeners[0]);
// Output debug messages
System.Diagnostics.Debug.Assert(false, "Message",
"Detail message to show in the debug window.");
Random rand = new Random(100);
System.Diagnostics.Debug.Indent();
System.Diagnostics.Debug.WriteLine("First random number: "
+ rand.Next().ToString());
System.Diagnostics.Debug.Unindent();
System.Diagnostics.Debug.WriteLineIf(rand.Next()%2 == 0,
"Even random number generated.");
Figure 4: Console Output
Possible Enhancements
Beyond the basics of using the Debug and Trace classes covered here, consider the following enhancements:
- Set up a listener through the configuration file—Rather than set up the listener via code, experiment with controlling it through the <listeners> element in the application configuration file.
- Set up the EventLogTraceListener—Configure the listener to output to the event log.
- Implement a custom Listener—Create additional listeners to log to alternative locations such as a database.
No comments:
Post a Comment