Tracing






Tracing

Tracing is a process for collecting information about program execution. Information revealed through tracing can help you resolve errors and issues with an application.

Using the TraceContext Class

The TraceContext class of the System.Web namespace is responsible for gathering execution details of a Web request. You can access the TraceContext object for the current request through the Trace property of the Page class. After you have the TraceContext object, you can invoke its member methods to write trace messages to the trace log. Figure lists some of the important members of the TraceContext class with which you should be familiar.

Figure Important Members of the TraceContext Class

Member

Type

Description

IsEnabled

Property

Specifies whether tracing is enabled for a request.

TraceMode

Property

Indicates the sort order in which the messages should be displayed. It can have one of three values—Default, SortByCategory, or SortByTime.

Warn()

Method

Writes the messages to the trace log in red, which indicates that they are warnings.

Write()

Method

Writes the messages in the trace log.

graphics/alert_icon.gif

The IsEnabled property can be dynamically assigned to turn tracing for a page on or off. It can also be used to include or exclude code based on the trace setting for a page.


You can enable tracing for a Page using the Trace attribute of the Page directive. When the Trace attribute is set to true in the Page directive, the page appends the tracing information of the current Web request with its output.

Take the following steps to enable tracing in a page and display debugging information:

  1. Open Visual Studio .NET and create a new blank solution named 315C13 at c:\inetpub\wwwroot\ExamCram. (You might need to change the directory based on your configuration.)

  2. Add a new Visual C# ASP.NET Web Application project at the following location: http://localhost/ExamCram/315C13/Example13_1.

  3. Change the pageLayout property of the DOCUMENT object to FlowLayout. Place one TextBox control (txtNumber), two Label controls (name one of them lblResult), and a Button control (btnCalculate) on the Web form.

  4. Switch to the HTML view of the form in the designer. Add the trace="true" attribute to the Page directive, like so:

    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs"
    AutoEventWireup="false" Inherits="Example13_1.WebForm1" Trace="true"%>
    
  5. Double-click the Button control and add the following code to the event handler to handle the Click event:

    private void btnCalculate_Click(object sender, System.EventArgs e)
    {
        // write a trace message
        Trace.Write("Factorial", "Inside Button Click event handler");
        int intNumber;
        try
        {
            intNumber = Convert.ToInt32(txtNumber.Text);
        }
        catch (Exception ex)
        {
            Trace.Warn("Factorial", "Invalid value", ex);
            return;
        }
        if(intNumber < 0)
        {
            Trace.Warn("Factorial", "Invalid negative value");
        }
        int intFac = 1;
        for (int i = 2; i <= intNumber; i++)
        {
            intFac = intFac * i;
            Trace.Write("Factorial", "Value of i: " + i);
        }
        if(intFac < 1)
            Trace.Warn("Factorial" , "There was an overflow");
        lblResult.Text = String.Format(
            "The factorial of {0} is {1}", intNumber, intFac);
        Trace.Write("Factorial" , "Done with computations.");
    }
    
  6. Run the project. Enter a small value, such as 5 into the number text box and click the Calculate Factorial button. You will see the factorial value displayed in the factorial text box, along with some trace messages in the Trace Information section.

  7. Try entering a negative value, or a larger value such as 100, and notice the trace messages displayed in the trace log. You should see warning messages displayed in red.

You can enable tracing for an entire Web application using the application configuration file (web.config). The <trace> element is used to configure tracing for an application; its attributes are as follows:

  • enabled— Indicates whether tracing is enabled for an application. If enabled, trace information can be viewed using the trace viewer.

  • localOnly— Indicates whether the trace viewer can be viewed by only the local client (running on the Web server itself) or by any client.

  • pageOutput— Indicates whether the trace information should be displayed along with the page output.

  • requestLimit— Indicates the number of requests whose trace information should be stored on the server. Tracing is disabled when the request limit is reached.

  • traceMode— Indicates the order in which the trace messages should be displayed in the Trace Information section of the trace log. It can be either SortByCategory (sorted by the Category column) or SortByTime (sorted by the First(s) column).

graphics/alert_icon.gif

The page-level trace setting overrides the trace setting for the application. For example, if pageOutput is set to false in the web.config file and the trace attribute is enabled at page level, the trace information is still displayed along with the page output.


Enabling tracing through the web.config file enables you to view the trace information using the trace viewer in a separate page (trace.axd) instead of displaying it with the page output. The following code segment shows how to modify the <trace> element defined in the <system.web> element of the web.config file:

<trace enabled="true" requestLimit="10"
    pageOutput="false" traceMode="SortByTime"
    localOnly="true" />

Conditional Compilation

The C# programming language provides a set of preprocessing directives (as listed in Figure). You can use these directives to skip sections of source files for compilation, report errors and warnings, or mark distinct regions of source code.

C# Preprocessing Directives

Directives

Description

#if, #else, #elif, and #endif

These directives conditionally skip sections of code. The skipped sections are not part of the compiled code.

#define and #undef

These directives define or undefine symbols in the code.

#warning and #error

These directives explicitly generate error or warning messages.

#line

This directive alters the line numbers and source filenames reported by the compiler in warning and error messages.

#region and #endregion

These directives mark sections of code. Visual Studio .NET uses these directives to show, hide, and format code.

The following example shows how to define a symbol named in your program:

#define MYSYMBOL

The following example shows how to use a preprocessor directive to include or exclude code from compilation:

#if MYSYMBOL
    // call ThisMethod() only when MYSYMBOL is defined
    ThisMethod();
#else
    // call ThisMethod() only when MYSYMBOL is NOT defined
    InitializeReleaseMode();
#endif

Another option for the conditional compilation is the Conditional attribute, which can be used to mark a method for conditional compilation. The Conditional attribute takes one argument that specifies a symbol. If the symbol definition is available, the code of the method is included; otherwise, the code of the method is excluded from the compiled code. For example, the call to the following method executes only if the DEBUG symbol is defined:

[Conditional("DEBUG")]
public void DebugMethod()
{
    // Method code goes here
}

graphics/alert_icon.gif

A method must have its return type set to void to have the Conditional attribute applied to it.


Visual Studio .NET provides two compilation configurations already set up for you: the Debug configuration and the Release configuration. The Debug configuration defines the DEBUG and the TRACE symbols, whereas the Release configuration defines only the TRACE symbol. You can define additional symbols and compilation configurations using the project's Property Pages dialog box in Visual Studio .NET.

Using the Trace and Debug Classes

Tracing in Visual C# .NET can also be done by generating messages about a program's execution with the use of the Debug and Trace classes.

The Debug and Trace classes both belong to the System.Diagnostics namespace and have members with the same names. The members of the Debug class are conditionally compiled only when the DEBUG symbol is defined. On the other hand, members of the Trace class are conditionally compiled only when the TRACE symbol is defined.

Figure summarizes the members of both the Debug and Trace classes.

Figure Members of the Debug and Trace Classes

Member

Type

Description

Assert()

Method

Checks for a condition and displays a message if the condition is false.

AutoFlush

Property

Specifies whether the Flush() method should be called on the listeners after every write.

Close()

Method

Flushes the output buffer and then closes the listeners.

Fail()

Method

Displays an error message.

Flush()

Method

Flushes the output buffer and causes the buffered data to be written to the listeners.

Listeners

Property

Specifies the collection of listeners that is monitoring the output generated by the Trace and Debug classes.

Write()

Method

Writes the given information to the trace listeners in the Listeners collection.

WriteIf()

Method

Writes the given information to the trace listeners in the Listeners collection only if a condition is true.

WriteLine()

Method

Acts the same as the Write() method but appends the information with a newline character.

WriteLineIf()

Method

Acts the same as the WriteIf() method but appends the information with a newline character.

For example, the following code segment displays the message only when the TRACE symbol is defined and when the expression intFac < 1 evaluates to true:

Trace.WriteLineIf(intFac < 1, "There was an overflow");

Trace Listeners

Listeners are the classes responsible for forwarding, recording, and displaying the messages generated by the Trace and Debug classes. You can have multiple listeners associated with Trace and Debug classes by adding Listener objects to their Listeners properties.

graphics/alert_icon.gif

Both the Debug and Trace classes share their Listeners collections, so an object added to the Listeners collection of the Debug class is automatically available in the Trace class and vice versa.


The TraceListener class is an abstract class that belongs to the System.Diagnostics namespace and has three implementations:

  • DefaultTraceListener class— An object of this class is automatically added to the Listeners collection. Its behavior is to write messages on the Output window.

  • TextWriterTraceListener class— An object of this class writes messages to any class that derives from the Stream class that includes the console or a file.

  • EventLogTraceListener class— An object of this class writes messages to the Windows event log.

You can also create a custom listener by inheriting from the TraceListener class. When doing so, you must at least implement the Write() and WriteLine() methods.

Trace Switches

Trace switches are used to control the level of tracing that needs to be done on a program. They can be set via a machinewide (machine.config) or applicationwide (web.config) configuration files that are Extensible Markup Language (XML) based. The application automatically picks up the changes from the configuration file when it restarts, which is especially useful when the application you are working with is in production mode.

Two predefined classes for creating trace switches are available—the BooleanSwitch class and the TraceSwitch class. Both of these classes derive from the abstract Switch class. You can also define your own trace switch classes by deriving classes from the Switch class.

You use the BooleanSwitch class to differentiate between two modes of tracing: trace-on or trace-off. Its default value is 0, which corresponds to the trace-off state. If it is set to any non-zero value, it corresponds to the trace-on state.

Unlike BooleanSwitch, the TraceSwitch class provides five levels of tracing switches. These levels are defined by the TraceLevel enumeration and are listed in Figure. The default value of TraceLevel for a TraceSwitch object is 0 (off).

Figure The TraceLevel Enumeration

Enumerated Value

Integer Value

Type of Tracing

Off

0

None

Error

1

Only error messages

Warning

2

Warning messages and error messages

Info

3

Informational messages, warning messages, and error messages

Verbose

4

Verbose messages, informational messages, warning messages, and error messages

graphics/alert_icon.gif

For a BooleanSwitch object, if any non-zero (negative or positive) value is specified in the configuration file, the BooleanSwitch object's Enabled property is set to true. For a TraceSwitch object, if a value greater than 4 is specified, the Level property of the object is set to TraceLevel.Verbose (4). If a negative value is specified, a StackOverflowException exception occurs at runtime.


Take the following steps to learn how to use trace switches in a Web application:

  1. Create a new Web application project (Example13_2) with the same user interface as Example13_1.

  2. Switch to code view and add the following using directive:

    using System.Diagnostics;
    
  3. Add the following code in the class definition:

    static TraceSwitch traceSwitch = new TraceSwitch("FactorialTrace",
              "Trace the factorial application");
    
  4. Add the following code to the Click event handler of the Calculate Factorial button:

    private void btnCalculate_Click(object sender, System.EventArgs e)
    {
        if (traceSwitch.TraceVerbose)
           // write a debug message
           Debug.WriteLine("Inside Button Click event handler");
    
        // start indenting messages now
        Debug.Indent();
        int intNumber = Convert.ToInt32(txtNumber.Text);
    
        if (traceSwitch.TraceError)
        {
            Debug.Assert(intNumber >= 0, "Invalid value",
               "negative value in debug mode");
        }
    
        int intFac = 1;
        for (int i = 2; i <= intNumber; i++)
        {
            intFac = intFac * i;
            // write a debug message
            if (traceSwitch.TraceInfo)
               Debug.WriteLine(i, "Factorial Program Debug, Value of i");
        }
    
        if (traceSwitch.TraceWarning)
            // write a debug message if the condition is true
            Debug.WriteLineIf(intFac < 1, "There was an overflow",
                 "Factorial Program Debug");
    
        lblResult.Text = String.Format(
               "The factorial of {0} is {1}", intNumber, intFac);
        // decrease the indent level
        Debug.Unindent();
    
        if (traceSwitch.TraceVerbose)
            // write a debug message
            Debug.WriteLine("Done with computations.");
    }
    
  5. Open the web.config file of the project; then insert the <system.diagnostics> element in the <configuration> element as shown here:

    <configuration>
        <system.diagnostics>
            <switches>
                <add name="FactorialTrace" value="4" />
            </switches>
        </system.diagnostics>
       <system.web>
       ...
              </system.web>
    </configuration>
    
  6. Set the project as the startup project for the solution and run the project using the Debug configuration. Enter a value of 5; note that all messages appear in the Visual Studio .NET Output window. Try again with a negative value and a large value. You see all the errors as well as all the warning messages. Close the form, and then modify the XML file by changing the value of FactorialTrace to 3. You should now see all the messages except the one in the if statement that checks for TraceLevel.Verbose. Repeat the process with the values of FactorialTrace in the configuration file changed to 2, 1, and 0.

  7. Modify the program to change all Debug statements to the Trace statements; then run the project using the Release configuration. Change the FactorialTrace switch value to 4 and then repeat the process discussed in step 6.


     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows