JavaScript Editor Javascript validator     Javascripts

Main Page


Previous Section Next Section

7.2 Tracing

Tracing is an easy way to find out what is going on in your program. Back in the days of classic ASP, the only way to trace what was happening in your code was to insert Response.Write statements in strategic places. This allowed you to see that you had reached a known point in the code, and perhaps to display the value of some variables. The big problem with this hand-tracing technique, aside from the amount of work involved, was that you had to laboriously remove or comment out all those statements before the program went into production.

ASP.NET provides better ways of gathering the trace information. You can add tracing at the application level or at the page level. With application-level tracing, every page is traced, while with page-level tracing, you choose the pages to which to add tracing.

7.2.1 Page-Level Tracing

To add page-level tracing, modify the Page directive at the top of the .aspx page, by adding a Trace attribute and setting its value to true, as follows:

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false"
     Inherits="DebuggingApp.WebForm1" Trace="true" %>

When you view this page, there will now be tables at the bottom that contain a wealth of information about your web application. Select a book from the drop-down list and you will see something like Figure 7-2.

Figure 7-2. Trace results
figs/pan2_0702.gif

The top section, labeled Request Details, shows basic information, including the SessionID, the Time of Request, Request Type, and Status Code (Table 7-1). Every time the page is posted to the server, this information is updated. If you change the selection (remember that AutoPostBack is set to true), you will see that the Time of Request is updated, but the SessionID remains constant.

The next section, labeled Trace Information, is the trace log, which provides lifecycle information. This includes elapsed times, in seconds, since the page was initialized (the From First(s) column) and since the previous event in the lifecycle (the From Last(s) column). You can add custom trace information to the trace log, as explained later in this chapter.

Table 7-1. Status codes

Category

Number

Description

Informational (100-199)

100

Continue

 

101

Switching protocols

Successful (200-299)

200

OK

 

204

No Content

Redirection (300-399)

301

Moved permanently

 

305

Use proxy

 

307

Temporary redirect

Client Errors (400-499)

400

Bad request

 

402

Payment required

 

404

Not found

 

408

Request timeout

 

417

Expectation failed

Server Errors (500-599)

500

Internal server error

 

503

Service unavailable

 

505

HTTP version not supported

The next section in the trace lists all the controls on the page in a hierarchical manner, including the name of the control, its type, and its size in bytes, both on the page and in the ViewState state bag.

This is followed by itemizations of the Cookies and Headers collections. Finally there is a list of all the server variables.

7.2.2 Inserting into the Trace Log

You can add custom information to the trace output by writing to the Trace object. This object exposes two methods for putting your own statements into the trace log, Write and Warn. The only difference between the two methods is that Warn writes to the log in red. The Warn and Write methods are overloaded to take either a single string, two strings, or two strings and an exception object. The following cases illustrate:

Trace.Warn("Warning Message")

Inserts a record into the trace log with the message passed in as a string.

Trace.Warn("Category","Warning Message")

Inserts a record into the trace log with the category and message you pass in.

Trace.Warn("Category","Warning Message", excp)

Inserts a record into the trace log with a category, warning message, and exception.

Example 7-5 contains the C# source code, and Example 7-6 contains the VB.NET source code for the Page_Load and ddlBooks_SelectedIndexChanged event procedures; this adds three messages to the trace. Changed lines of code are indicated in boldface.

Example 7-5. Writing to the Trace object in C#
private void Page_Load(object sender, System.EventArgs e) 
{
   // Put user code to initialize the page here
   Trace.Write("In Page_Load");
   if (! IsPostBack)
   {
      Trace.Write("Page_Load", "Not Postback.");
      //  Build 2 dimensional array for the lists
      //  First dimension contains bookname
      //  2nd dimension contains ISBN number
      string[,] books = {
        {"Programming C#","0596001177"},
        {"Programming ASP.NET","1234567890"},
        {"WebClasses From Scratch","0789721260"},
        {"Teach Yourself C++ in 21 Days","067232072X"},
        {"Teach Yourself C++ in 10 Minutes","067231603X"},
        {"XML & Java From Scratch","0789724766"},
        {"Complete Idiot's Guide to a Career in Computer Programming","0789719959"},
        {"XML Web Documents From Scratch","0789723166"},
        {"Clouds To Code","1861000952"},
        {"C++: An Introduction to Programming","1575760614"},
        {"C++ Unleashed","0672312395"}
                        };
      
      //  Now populate the lists.
      int i;
      for (i = 0; i < books.GetLength(0); i++)
      {
         //  Add both Text and Value
         ddlBooks.Items.Add(new ListItem(books[i,0],books[i,1]));
      }
   }
}

private void ddlBooks_SelectedIndexChanged(object sender, System.EventArgs e)
{
   // Force an exception
   try
   {
      int a = 0;
      int b = 5/a;
   }
   catch (System.Exception ex)
   {
      Trace.Warn("UserAction","Calling b=5/a",ex);
   }

   //  Check to verify that something has been selected.
   if (ddlBooks.SelectedIndex != -1)
   {
      lblDdl.Text=ddlBooks.SelectedItem.Text + " ---> ISBN: " +
         ddlBooks.SelectedItem.Value;
   }   
}
Example 7-6. Writing to the Trace object in VB.NET
Private Sub Page_Load(ByVal sender As System.Object, _
                      ByVal e As System.EventArgs) Handles MyBase.Load
   'Put user code to initialize the page here
   Trace.Write("In Page_Load")
   If Not IsPostBack Then
      '  Build 2 dimensional array for the lists
      '  First dimension contains bookname
      '  2nd dimension contains ISBN number
      Trace.Write("Page_Load", "Not Postback.")
      Dim books(,) As String = { _
         {"Programming C#", "0596001177"}, _
         {"Programming ASP.NET", "1234567890"}, _
         {"WebClasses From Scratch", "0789721260"}, _
         {"Teach Yourself C++ in 21 Days", "067232072X"}, _
         {"Teach Yourself C++ in 10 Minutes", "067231603X"}, _
         {"XML & Java From Scratch", "0789724766"}, _
         {"Complete Idiot's Guide to a Career in Computer Programming", _
                     "0789719959"}, _
         {"XML Web Documents From Scratch", "0789723166"}, _
         {"Clouds To Code", "1861000952"}, _
         {"C++: An Introduction to Programming", "1575760614"}, _
         {"C++ Unleashed", "0672312395"} _
      }

      '  Now populate the lists.
      Dim i As Integer

      For i = 0 To books.GetLength(0) - 1
         '  Add both Text and Value
         ddlBooks.Items.Add(New ListItem(books(i, 0), books(i, 1)))
      Next

   End If
End Sub

Private Sub ddlBooks_SelectedIndexChanged(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles ddlBooks.SelectedIndexChanged
   ' Force an exception
   Try
      Dim a As Integer = 0
      Dim b As Integer = 5 / a
   Catch ex As System.Exception
      Trace.Warn("UserAction", "Calling b=5/a", ex)
   End Try

   '  Check to verify that something has been selected.
   If ddlBooks.SelectedIndex <> -1 Then
      lblDdl.Text = ddlBooks.SelectedItem.Text & " ---> ISBN: " & _
                    ddlBooks.SelectedItem.Value
   End If
End Sub

The first message is added in the Page_Load method to signal that you've entered that method:

Trace.Write("In Page_Load");

The second message is added if the page is not a postback:

if (! IsPostBack)
{
   Trace.Write("Page_Load", "Not Postback.");

This second message is categorized as Page_Load; using a category can help you organize the trace output. The effect of these two Write statements is shown in Figure 7-3. Shading was added to make it easy to see these two statements.

Figure 7-3. Two Trace.Write statements
figs/pan2_0703.gif

The third message is added to demonstrate the process of inserting an exception into the error log. The ddlBooks_SelectedIndexChanged event handler also contains code to force an exception by dividing by zero. The code catches that exception and logs the exception with a trace statement, as shown by the following code fragment:

try
{
   int a = 0;
   int b = 5/a;
}
catch (System.Exception ex)
{
   Trace.Warn("UserAction","Calling b=5/a",ex);
}

Exceptions are an advanced error handling technique that allows you to try potentially dangerous code and catch any exception objects thrown by the operating system or by other parts of your own code. You might use exceptions when reading a file; if the file cannot be opened, the system will throw an exception. Exception handling is beyond the scope of this book, but is covered in Jesse Liberty's book Programming C#, Third Edition (O'Reilly).

The output from this trace statement is shown in Figure 7-4.

Figure 7-4. Trace statement output
figs/pan2_0704.gif

Because this trace statement was written calling the Warn method rather than the Write method, the trace output appears in red onscreen (though not in your copy of this book). Notice that string you passed in, Calling b=5/a, is displayed, followed by an error message extracted automatically from the exception object.

Not only is it easy to implement trace statements, but when it is time to put your page into production, all these statements can remain in place. The only modification you need to make is to change the Trace attribute in the Page directive from true to false.

7.2.3 Application-Level Tracing

Application-level tracing applies to all the pages in a given application. It is configured through the web.config file, which will be described more fully in Chapter 20.

The web.config file is typically located in the virtual root directory of the application. If there is a web.config file in a subdirectory of the virtual root, then that copy will apply only to the pages in that subdirectory and in the subdirectories under it. If tracing is enabled application-wide from the root directory, tracing will be applied across the application uniformly. The exception is when a specific page has a contradictory page directive, which supersedes the application directive.

Web.config is an XML file that consists of sections delimited by tags. The trace configuration information is contained in the <trace> section within the <system.web> section, which is contained within the <configuration> section.

Web.config, like all XML documents, must consist of well-formed XML. The elements of a well-formed XML file are discussed in a sidebar in Chapter 4. Note that XML is case-sensitive.

A typical trace configuration snippet will look something like Example 7-7.

Example 7-7. Trace code snippet from web.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
  <system.web>
.
.
.
    <trace
        enabled="true"
        requestLimit="10"
        pageOutput="false"
        traceMode="SortByTime"
        localOnly="true"
    />

You can easily edit the web.config file in VS.NET by double-clicking on the file in the Solution Explorer. (If the Solution Explorer is not visible, click on the View/Solution Explorer menu item.) Alternatively, this file can be edited in any text editor.

There are five possible properties in the <trace> section. These properties appear in Table 7-2. Several of these properties affect the trace viewer, which will be described in the following section.

Table 7-2. Trace section properties

Property

Values

Description

enabled

true, false

Enables or disables application-level tracing. Default is false.

If enabled, then all pages in the application will display trace information unless a specific page has "Trace = false" in the Page directive.

requestLimit

Integer

Number of trace requests that will be stored on the server and visible in the trace viewer. Default is 10.

pageOutput

true, false

Dictates if trace information is displayed on both the application pages and in the trace viewer. Default is false.

Pages with tracing enabled are not affected by this setting.

traceMode

SortByTime, SortByCategory

Dictates whether the trace log is sorted by Time or Category. Default is TraceMode.SortByTime.

localOnly

true, false

Indicates if the trace viewer is available only on the host web server. Default is true.

7.2.4 Trace Viewer

If application-level tracing is enabled, the trace log can be viewed directly from your browser for any application, even across multiple page requests. The trace facility provides a trace viewer, called trace.axd. Aim your browser toward trace.axd as though it were a page in the application, with the following URL, for example:

http://localhost/DebuggingApp/trace.axd

You will see a summary of all the entries in the trace log, as shown in Figure 7-5.

Figure 7-5. Trace viewer
figs/pan2_0705.gif

Clicking on any of the View Details links will bring you to the same page as would be seen in page-level tracing for that page.

    Previous Section Next Section


    JavaScript Editor Javascript validator     Javascripts 




    ©