In this tutorial you will learn about Tracing, Using Trace and Debug to display information, Code Tracing and Debugging, Output from Tracing, The six Debug Members and Trace Methods, Trace Listeners, Types of predefined Trace Listeners, Trace Switches, Conditional Compilation and Conditional Compilation Constants.
As explained earlier, Tracing is a method of monitoring the execution of the application while it is running. Tracing and debugging instrumentation can be added to the .NET application when it is being developed, and that instrumentation can be used both while developing the application and after it has been deployed. With the Trace and Debug classes, information can be recorded about errors and application execution to logs, text files, or other devices for later analysis.
Instrumenting the application by placing trace statements at strategic locations in the code is especially useful for distributed applications. With trace statements an application can be instrumented to display information when things go wrong. This information can be displayed to monitor how well the application is performing.
The Trace and Debug classes are identical except that procedures and functions of the Trace class are compiled by default into release builds, but those of the Debug class are not. Let us see how instrumentation is used in applications.
The Trace and Debug classes provide the means to monitor and examine application performance either during development or after deployment. For example, the Trace class can be used to track particular types of actions in a deployed application as they occur (for example, creation of new database connections), and can therefore monitor the application's efficiency.
The output methods of the Debug class can be used to display messages during development. For example:
Each of these examples will display "Hello World!" in the Output window when the application is run in the debugger.
Trace output is collected by objects called listeners. A listener is an object that receives trace output and writes it to an output device (usually a window, log, or text file). When a trace listener is created, it is typically added to the Trace.Listeners collection, allowing the listener to receive all trace output.
Tracing information is always written at least to the default Trace output target, the DefaultTraceListener. If for some reason the DefaultTraceListener has been deleted without adding any other listeners to the Listeners collection, tracing messages will not be received.
The six Debug Members and Trace methods that write tracing information are listed in the following table.
Method and Output
Assert - The specified text; or, if none is specified, the Call Stack. The output is written only if the condition specified as an argument in the Assert statement is false.
Fail - The specified text; or, if none is specified, the Call Stack.
Write - The specified text.
WriteIf - The specified text, if the condition specified as an argument in the WriteIf statement is satisfied.
WriteLine - The specified text and a carriage return.
WriteLineIf - The specified text and a carriage return, if the condition specified as an argument in the WriteLineIf statement is satisfied.
All listeners in the Listeners collection receive the messages described in the above table, but the actions taken may vary depending on what kind of listener receives the message. For example, the DefaultTraceListener displays an assertion dialog box when it receives a Fail or failed Assert notification, but a TextWriterTraceListener simply writes the output to its stream.
Custom results can be produced by implementing a user defined listener. A custom trace listener might, for example, displays the messages to a message box, or connects to a database to add messages to a table. All custom listeners should support the six methods mentioned above.
In Visual Basic.NET 2005, the Debug.Write, Debug.WriteIf, Debug.WriteLine, and Debug.WriteLineIf methods have been replaced with the Debug.Print method that was available in earlier versions of Visual Basic.
The Write and WriteLine methods always write the text that is specified. Assert, WriteIf, and WriteLineIf require a Boolean argument that controls whether or not they write the specified text; they write the specified text only if the expression is true (for WriteIf and WriteLineIf), or false (for Assert). The Fail method always writes the specified text.
When using Trace and Debug, a mechanism for collecting and recording the messages that are sent is to be put in place. Trace messages are received by listeners. The purpose of a listener is to collect, store, and route tracing messages. Listeners direct the tracing output to an appropriate target, such as a log, window, or text file.
Listeners are available to both the Debug class and the Trace class, each of which can send its output to a variety of listener objects. There are three types of predefined listeners:
By default the DefaultTraceListener receives the Debug and Trace output. It the user requires the output to be routed to another Listener the same must be specified and added to the collection. Any listener in the Listeners collection gets the same messages from the trace output methods. If two listeners are set up --a TextWriterTraceListener and an EventLogTraceListener, each listener receives the same message. The TextWriterTraceListener would direct its output to a stream, and the EventLogTraceListener would direct its output to an event log.
The following example shows how to send output to the Listeners collection.
' Use this example when debugging.
Debug.WriteLine("Error in Widget 42")
' Use this example when tracing.
Trace.WriteLine("Error in Widget 42")
Trace switches allow the user enable, disable, and filter tracing output. They are objects that exist in the code and can be configured externally through the .config file. There are two types of trace switches provided in the .NET Framework: BooleanSwitch Class and TraceSwitch Class. The BooleanSwitch class acts as a toggle switch, either enabling or disabling a variety of trace statements. The TraceSwitch class allows the user enable a trace switch for a particular tracing level so that the trace messages specified for that level and all levels below it appear. If the switch is disabled, the trace messages will not appear. Both these classes derive from the abstract (MustInherit) class Switch, as should any user-developed switches.
Trace switches can be useful for filtering information. For example, a user, might want to see every tracing message in a data access module, but only error messages in the rest of the application. In that case, one trace switch would be used for the data access module and one switch for the rest of the application. By using the .config file to configure the switches to the appropriate settings, types of trace messages can be controlled.
Typically, a deployed application is executed with its switches disabled, so that users need not observe a lot of irrelevant trace messages appearing on a screen or filling up a log file as the application runs. If a problem arises during application execution, you can stop the application, enable the switches, and restart the application. Then the tracing messages will be displayed.
To use a switch, a switch object must be created from a BooleanSwitch class, a TraceSwitch class, or a developer-defined switch class. Then a configuration value can be set to specify when the switch object is to be used. The setting of the switch object is tested in various Trace (or Debug) tracing methods.