Tracing and Monitoring Your Application


In the following sections, you learn how to trace the execution of your ASP.NET application and monitor its performance. First, you learn how to enable tracing for both pages and applications. By taking advantage of tracing, you can make your pages easier to debug.

Next , you examine how to monitor the ASP.NET process and automatically restart an ASP.NET application when problems are detected . You learn how to configure the ASP.NET process model.

You also learn methods for reading and adding information to the server event log and create custom event logs to monitor the health of your ASP.NET application.

Finally, you learn how to work with performance counters. I provide an overview of the performance counters included with the ASP.NET framework that you can use to monitor the performance of your application. You also learn how to create custom performance counters.

Tracing Page Execution

You can trace the execution of an ASP.NET page by using the trace attribute of the page directive. To enable tracing for a single ASP.NET page, include the following directive at the top of the page:

 
 <%@ Page Trace="True" %> 

When tracing is enabled for a page, trace information is automatically appended to the bottom of the page (see Figure 18.7). The trace information includes the following statistics:

  • Request Details ” Displays such information as the user 's unique session ID, time of the request, and status code returned by the server for the request.

  • Trace Information ” Displays information about the steps in page execution. The execution time for each step is displayed in seconds.

  • Control Tree ” Displays the hierarchy of controls in a page. Both the render size and view state size for each control are displayed in bytes.

  • Session State ” Displays each item stored in session state.

  • Application State ” Displays each item stored in application state.

  • Cookies Collection ” Displays the name and value of all cookies stored on the browser.

  • Headers Collection ” Displays all the browser headers sent to the server.

  • Form Collection ” Displays the name and value of each item submitted with an HTML form.

  • QueryString Collection ” Displays the name and value of each item submitted in a query string.

  • Server Variables ” Displays a list of all the server variables (browser headers and environmental variables).

Figure 18.7. Page with tracing enabled.

graphics/18fig07.jpg

All sections are not necessarily displayed when tracing is enabled. For example, the Form Collection section is displayed only when form data has actually been posted.

Notice that you can use the information from the Control Tree section to determine the size of the view state for each control. Because view state must be stored in the hidden __VIEWSTATE form field and passing a large hidden form field can significantly affect the rendering speed of a page, limiting the size of view state is a wise idea. You can use the Control Tree section to identify the controls using the most view state.

The Trace Information section provides information about the methods called to render the page. The ASP.NET framework automatically inserts certain messages into this section. For example, information about the page Init and PreRender events is automatically inserted into this section.

Adding Custom Trace Messages

You can add your own custom trace messages to the Trace Information section. Adding custom trace messages is valuable for debugging an application. While you're in the process of debugging a page, you can enable tracing and view all your custom trace messages. For example, you can display the value of variables at different points of page execution. When you are satisfied with the page, you can simply turn off tracing and hide all your messages.

ASP CLASSIC NOTE

In Classic Active Server Pages, the only trace tool was the Response.Write statement. Typically, you were forced to isolate errors by adding Response.Write statements throughout the page. If you forgot to comment out a Response.Write statement that you added for debugging purposes, the entire world would see your debugging information.


To add custom trace messages, use either the Trace.Warn or Trace.Write methods. The only difference between these methods is that Trace.Warn displays messages in a red font and Trace.Write displays messages in a black font.

The page in Listing 18.16, for example, adds custom trace messages to the Trace Information section (see Figure 18.8).

Listing 18.16 Trace.aspx
 <%@ Page Trace="True" %> <Script Runat="Server"> Sub Page_Load   Trace.Warn( "Page Loading" ) End Sub Sub Button_Click( s As Object, e As EventArgs )   Trace.Warn( "The value of favColor is " & txtFavColor.Text )   lblMessage.Text = "Button Clicked!" End Sub </Script> <html> <head><title>Trace.aspx</title></html> <body> <form Runat="Server"> <h2>Enter your Favorite Color</h2> <b>Favorite Color:<b> <br> <asp:TextBox   ID="txtFavColor"   Runat="Server" /> <asp:Button   Text="Click Here!"   OnClick="Button_Click"   Runat="Server" /> <p> <asp:Label   ID="lblMessage"   Runat="Server" /> </form> </body> </html> 

The C# version of this code can be found on the CD-ROM.

Figure 18.8. Page with tracing enabled.

graphics/18fig08.jpg

In Listing 18.16, trace messages are displayed in both the Page_Load and Button_Click subroutines. For example, the trace message in the Button_Click subroutine displays the value that the user entered into the TextBox control.

Detecting Whether Tracing Is Enabled

If you need to execute code only when tracing is enabled, you can use the Trace.IsEnabled property to detect whether tracing is currently enabled or disabled for a page. For example, suppose that you want to display all the items in a collection in a trace message. The page in Listing 18.17 creates a string that contains the values of all the items in a collection only when tracing is enabled.

Listing 18.17 TraceIsEnabled.aspx
 <%@ Page Trace="True" %> <Script Runat="Server"> Sub Page_Load   Dim colArrayList As ArrayList   colArrayList = New ArrayList()   colArrayList.Add( "red" )   colArrayList.Add( "green" )   colArrayList.Add( "aliceblue" )   If Trace.IsEnabled Then     Dim strTraceMessage As String     Dim strItem As String     For Each strItem in colArrayList       strTraceMessage &= strItem & ","     Next     Trace.Warn( strTraceMessage )   End If   dropColors.DataSource = colArrayList   dropColors.DataBind End Sub </Script> <html> <head><title>TraceIsEnabled.aspx</title></html> <body> <form Runat="Server"> <h2>Enter your Favorite Color</h2> <b>Favorite Color:<b> <asp:DropDownList   ID="dropColors"   Runat="Server" /> </form> </body> </html> 

The C# version of this code can be found on the CD-ROM.

When tracing is enabled, the page in Listing 18.17 displays all the items in an ArrayList in a trace message. When tracing is disabled ”the Trace page directive has the value False ”the trace message is not created.

Creating Trace Categories

By default, trace messages are displayed in order of execution. For example, a trace message added within the Page_Load subroutine will be displayed before a trace message added in the Page_PreRender subroutine.

Instead of displaying trace messages in order of execution, you can create different categories for trace messages and group the messages into the categories. For example, you could create distinct categories for database trace messages and form trace messages. The page in Listing 18.18 illustrates how to group trace messages into different categories.

Listing 18.18 TraceCategories.aspx
 <%@ Page Trace="True" TraceMode="SortByCategory" %> <%@ Import Namespace="System.Data.SqlClient" %> <Script Runat="Server"> Sub Page_Load   Dim conPubs As SqlConnection   Dim cmdSelect As SqlCommand   conPubs = New SqlConnection( "Server=Localhost;UID=sa;PWD=secret; Database=Pubs" )   cmdSelect = New SqlCommand( "SELECT au_lname FROM Authors", conPubs )   Trace.Warn( "Database", "Opening Connection" )   conPubs.Open()     dropAuthors.DataSource = cmdSelect.ExecuteReader()     dropAuthors.DataTextField = "au_lname"     Trace.Warn( "Database", "Binding to DropDownList" )     dropAuthors.DataBind   Trace.Warn( "Database", "Closing Connection" )   conPubs.Close() End Sub Sub Button_Click( s As Object, e As EventArgs )   Trace.Warn( "Form", "User selected " & dropAuthors.SelectedItem.Text ) End Sub </Script> <html> <head><title>TraceCategories.aspx</title></head> <body> <form Runat="Server"> <h2>Choose an Author</h2> <b>Author Last Name:<b> <asp:DropDownList   ID="dropAuthors"   Runat="Server" /> <asp:Button   Text="Select!"   OnClick="Button_Click"   Runat="Server" /> </form> </body> </html> 

The C# version of this code can be found on the CD-ROM.

Notice that the page directive at the top of the page in Listing 18.18 contains a TraceMode attribute. This attribute can have one of two values: SortByTime or SortByCategory . Because you want to group trace messages by category, you set TraceMode to the value SortByCategory .

When each trace message is created with the Trace.Warn statement, the category is specified. For example, the following Trace.Warn statement creates a trace message in the category Database :

 
 Trace.Warn( "Database", "Opening Connection" ) 

You can, of course, invent any categories you please . All your custom trace messages appear at the bottom of the Trace Information section.

Displaying Errors in Trace Messages

If you use TRY...CATCH statements in your ASP.NET pages to gracefully handle errors (as you should), errors are not displayed in the page when something goes wrong. The lack of error messages can make the process of debugging a page difficult. Fortunately, you can display the errors caught in TRY...CATCH statements within trace messages.

The page in Listing 18.19, for example, contains an error. The statement that causes the error is wrapped in a TRY...CATCH statement, so the error is not displayed in the page. However, the error is displayed within a trace message.

Listing 18.19 TraceException.aspx
 <%@ Page Trace="True" %> <Script Runat="Server"> Sub Page_Load   Dim txtTextBox As TextBox   Try     txtTextBox.Text = "Hello!"   Catch objException As Exception     Trace.Warn( "Page Errors", "Assigning Value To TextBox", objException )   End Try End Sub </Script> <html> <head><title>TraceException.aspx</title></head> <body> <h2>This page contains an error!</h2> </body> </html> 

The C# version of this code can be found on the CD-ROM.

In Listing 18.19, you pass three parameters to the Trace.Warn method: the category of the trace message, the text of the trace message, and the exception caught in the TRY...CATCH block. The values of all three parameters are displayed in the Trace Information section when tracing is enabled.

Using Application-Level Tracing

You can use a special page, named trace.axd , to view trace information collected from all the pages in your application. By default, the trace.axd page automatically displays a list of the first 10 requests to your application after application tracing is enabled. A View Details link appears next to each item in the list, linking to a page that shows detailed trace information for that request (see Figure 18.9).

Figure 18.9. Application-level tracing.

graphics/18fig09.jpg

Before you can use the trace.axd page, you must enable application-level tracing within either the Machine.Config file or root Web.Config file for your application. The Web.Config file in Listing 18.20 contains the necessary values to enable application-level tracing. (You can find this file in the AppTrace directory on the CD that accompanies this book.)

Listing 18.20 AppTrace/Web.Config
 <configuration>   <system.web>   <trace     enabled="true"     requestLimit="50"     pageOutput="false"     traceMode="SortByTime"     localOnly="true" />   </system.web> </configuration> 

The C# version of this code can be found on the CD-ROM.

The Web.Config file in Listing 18.20 enables application-level tracing on the local machine. It specifies that trace statistics should be stored for the last 50 requests.

The trace configuration section contains the following five elements:

  • enabled ” A Boolean value that indicates whether tracing is enabled for the application. The default value is true .

  • requestLimit ” The number of requests to list in the trace.axd page. The default value is 10 .

  • pageOutput ” A Boolean value that indicates whether trace information is displayed at the bottom of every page in the application. The default value is false .

  • traceMode ” A value that indicates the order in which trace messages are displayed. Possible values are SortByTime and SortByCategory ; the default value is SortByTime .

  • localOnly ” A Boolean value that indicates whether trace messages should be displayed only on the local computer, not remote computers. The default value is true .

CAUTION

If you want to disable the trace.axd page on a production Web site, you need to remove the reference to the trace page handler in the Machine.Config file. You can remove this entry from the httpHandlers section.


Monitoring the ASP.NET Process

ASP.NET applications execute in a separate process from the Web server. The Web server executes in a process named inetinfo.exe , and ASP.NET applications execute in a process named aspnet_wp.exe (the ASP.NET worker process).

You can modify several configuration settings that affect the behavior of the ASP.NET process. These configuration settings can be divided into two groups. The first group enables you to automatically restart the ASP.NET process in response to problems such as memory leaks, deadlocks, and access violations:

  • memoryLimit ” The percentage of system memory that the ASP.NET process is allowed to consume . By default, this setting has the value 80 , which stands for 80% of system memory. ( memoryLimit refers to the percentage of physical memory, not the percentage of virtual memory.)

  • requestQueueLimit ” The maximum number of queued requests. By default, this setting has the value 5000 , which stands for 5,000 requests.

  • shutdownTimeout ” The amount of time that the ASP.NET process is allowed to gracefully shut down. By default, this setting has the value 00:00:05 , which stands for 5 seconds.

When the ASP.NET worker process exceeds the memory or request queue limit, the process is automatically shut down and replaced by a new worker process. All the pending requests to the old process are automatically transferred to the new process. In theory, this should mean that the handoff between processes should be undetectable to the users of the application.

You can modify these settings in the <processModel> section of the Machine.Config file. These setting are read directly by aspnet_isapi.dll when the ASP.NET worker process is started.

The second group of configuration settings enables you to automatically restart the ASP.NET process after a certain amount of time or a certain number of requests:

  • idleTimeout ” The amount of idle time before the ASP.NET process is automatically shut down. The value is specified in hours, minutes, and seconds represented by a string in the format 99:99:99 . By default, this setting has the value infinite , which indicates that the ASP.NET process should never be shut down.

  • requestLimit ” The number of requests before the ASP.NET process is shut down. By default, this setting has the value infinite , which indicates that the ASP.NET process should never be shut down.

  • timeout ” The amount of time before the ASP.NET process is automatically shut down. The value is specified in hours, minutes, and seconds represented by a string in the format 99:99:99 . By default, this setting has the value infinite , which indicates that the ASP.NET process should never be shut down.

You can use these settings to automatically recycle the ASP.NET process every so often, to reclaim memory lost to memory leaks or dump bad code from memory. For example, the following processModel section automatically shuts down the ASP.NET process once every 24 hours:

 
 <processModel   enable="true"   timeout="24:00:00" /> 

You can test processModel configuration settings by using the page in Listing 18.21.

CAUTION

The page in Listing 18.21 is designed to crash the ASP.NET process by consuming too much memory.


Listing 18.21 ProcessModel.aspx
 <%@ Import Namespace="System.IO" %> <Script Runat="Server"> Sub Page_Load   Dim objStream As MemoryStream   objStream = Application( "Stream" )   If IsNothing( objStream ) Then     objStream = New MemoryStream()     objStream.WriteByte( 255 )   End If   objStream.WriteTo( objStream )   Application( "Stream" ) = objStream   lblMemory.Text = objStream.Length   lblProcessID.Text = _     ProcessModelInfo.GetCurrentProcessInfo.ProcessID End Sub </Script> <html> <head><title>ProcessModel.aspx</title></head> <body> Memory Consumed: <asp:Label   ID="lblMemory"   Runat="Server" /> bytes <p> Process ID: <asp:Label   ID="lblProcessID"   Runat="Server" /> </body> </html> 

The C# version of this code can be found on the CD-ROM.

The page in Listing 18.21 doubles the amount of memory that it consumes every time you request it. It also displays the ID of the current process. Notice that when you pass a certain threshold ”the percentage of physical memory specified by the memoryLimit setting ”a new process automatically replaces the current process.

Retrieving Process Information

You can use the ProcessModelInfo class to retrieve information about the ASP.NET process. The GetCurrentProcessInfo method returns information about the ASP.NET process currently executing, and the GetProcessInfoHistory method returns a history of ASP.NET processes.

Both methods return instances of the ProcessInfo class, which has the following properties:

  • Age ” A TimeSpan value that represents the length of time the ASP.NET process has been running

  • PeakMemoryUsed ” The maximum amount of memory used by the ASP.NET process in bytes

  • ProcessID ” An integer that represents the ID of the ASP.NET process

  • RequestCount ” An integer that represents the number of requests handled by the ASP.NET process

  • ShutdownReason ” A value representing the reason the ASP.NET process shut down (for example, MemoryLimitExceeded )

  • StartTime ” A DateTime value representing the date and time the ASP.NET process was started

  • Status ” The status of the ASP.NET process (for example, Alive or Shutdown ).

The page in Listing 18.22, for example, displays information about the last 10 ASP.NET processes (see Figure 18.10).

Listing 18.22 ProcessHistory.aspx
 <Script Runat="Server"> Sub Page_Load   dgrdHistory.DataSource = ProcessModelInfo.GetHistory( 10 )   dgrdHistory.Databind() End Sub </Script> <html> <head><title>ProcessHistory.aspx</title></head> <body> <asp:DataGrid   ID="dgrdHistory"   CellPadding="15"   AutoGenerateColumns="False"   Runat="Server"> <Columns>   <asp:BoundColumn     HeaderText="ProcessID"     DataField="ProcessID"/>   <asp:BoundColumn     HeaderText="Age"     DataField="Age"/>   <asp:BoundColumn     HeaderText="PeakMemoryUsed"     DataField="PeakMemoryUsed"/>   <asp:BoundColumn     HeaderText="RequestCount"     DataField="RequestCount"/>   <asp:BoundColumn     HeaderText="ShutdownReason"     DataField="ShutdownReason"/>   <asp:BoundColumn     HeaderText="StartTime"     DataField="StartTime"/>   <asp:BoundColumn     HeaderText="Status"     DataField="Status"/> </Columns> </asp:DataGrid> </body> </html> 

The C# version of this code can be found on the CD-ROM.

Figure 18.10. Viewing process history.

graphics/18fig10.jpg



ASP.NET Unleashed
ASP.NET 4 Unleashed
ISBN: 0672331128
EAN: 2147483647
Year: 2003
Pages: 263

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net