April 03, 2006 12:04 AM

Understanding the ASP.NET Lifecycle (Redux)

Logging and Troubleshooting
DevConnections
Rating: (0)

CoverStory

LANGUAGES:C#

ASP.NETVERSIONS: 2.0

 

Understanding the ASP.NET Lifecycle (Redux)

Logging and Troubleshooting

 

 

Understanding the lifecycle of ASP.NET pages is vital totroubleshooting issues in ASP.NET applications. Logging can be strategicallyadded to events using the .NET Framework?s built-in tracing. These logs can aidin pinpointing the causes of performance bottlenecks, as well as in gatheringusage statistics for your applications. This article explains the key steps inthe lifecycle of a page. It also shows how to easily integrate tracing intothese steps, and how to use these logs in conjunction with other tools totroubleshoot performance. This article employs C# with .NET Framework 2.0 andVisual Studio .NET 2005, but the concepts apply to .NET Framework 1.0 and 1.1.(This article has been adapted from Understandingthe ASP.NET Lifecycle: Logging and Troubleshooting published in the October2004 issue of asp.netPRO, with theconsent and cooperation of the author, Luther Miller.)

 

Many things happen behind the scenes when an ASP.NET pageis invoked. Eventually, the code in the page is processed, and an HTML responseis sent back to the client. For a good overview of this process, see ?ASP.NETPage Life Cycle Overview? (?Visual Web Developer/Web Pages? sub-topichierarchy) in the Visual Studio 2005 documentation. But what processingactually takes place? When does authentication take place? When does the view stateget parsed and processed? When does a button click event get fired? The answersare in the .NET Framework documentation ? but not necessarily where you?dexpect to find them.

 

Look for a page titled ASP.NET Web Server Control EventModel in the Visual Web Developer/Web Pages sub-topic hierarchy of the VisualStudio 2005 documentation. With the realization that an ASP.NET Page is aspecial type of ASP.NET control, this document explains the lifecycle of a page.The table in this document lists all the phases of the life of a control, aswell as the methods that correspond to each step. Some of the methods also havecorresponding events. For example, the Load step corresponds to the OnLoadmethod and fires the Load event. Visual Studio creates the Page_Load method andhooks it up to the Load event for you when you create a new page. Some of thesteps, such as Load View State and Render, don?t fire events,although they have methods that you can override.

 

Page processing is simply a part of what takes place whena request is handled by ASP.NET. Find ASP.NET Application Life Cycle Overviewunder ASP.NET Life Cycle in the Visual Web Developer/Web Pages sub-topichierarchy of Visual Studio 2005 documentation. This document contains a tablethat lists events and the order in which they are fired. You can write code forthese events and place it in the Global.asax file. Note that a Page is a typeof HTTP handler, so the part of this list that refers to ?the handler isexecuted? is essentially where all the Page?s lifecycle steps take place.Combining the events and methods from the HttpApplication class with the Pageclass yields a complete picture of what happens when a request is handled (seeFigure 1).

 

Object

Step

Description

HttpApplication

*BeginRequest

Request processing is starting.

HttpApplication

*AuthenticateRequest

User has been identified.

HttpApplication

AuthorizeRequest

User authorization has been verified.

HttpApplication

ResolveRequestCache

[The handler is created.]

See if response can be retrieved from cache, avoiding handler execution.

HttpApplication

AcquireRequestState

Session state for current request acquired.

HttpApplication

PreRequestHandlerExecute

[The handler is executed.]

Handler (Page) is about to be executed.

Page

Init event (OnInit method)

Initialize settings needed in the Page.

Page

LoadViewState method

ViewState is processed and state is restored to controls.

Some Controls

LoadPostData method

Process postback data and update controls; only controls that implement IpostBackDataHandler.

Page

Load event

(OnLoad method)

Execute any code common to all requests for the page.

Some Controls

RaisePostDataChangedEvent method

Raise events such as TextBox Changed; only controls that implement IpostBackDataHandler.

Page

RaisePostBackEvent method

Raise events such as Button Click.

Page

PreRender event (OnPreRender method)

Chance to make changes before state is saved and page is rendered.

Page

SaveViewState method

State of controls is saved.

Page

Render method

The page?s response is created.

Page

Dispose method

Final cleanup.

Page

Unload event (OnUnload method)

Another chance for final cleanup, but Dispose is where cleanup should occur.

HttpApplication

PostRequestHandlerExecute

Handler (Page) execution has finished.

HttpApplication

ReleaseRequestState

[Response output filtered.]

Session state gets saved.

HttpApplication

UpdateRequestCache

Provide opportunity for response to be added to the cache for future requests.

HttpApplication

*EndRequest

Request processing is finished.

*Included by default in global.asax.

Figure 1: The phases of the life of acontrol, as well as the methods that correspond to each step.

 

How can you take advantage of this information? Using the.NET Framework?s tracing classes, we can simply add a line of code that writesthe date, time, and some other basic information to a file whenever any ofthese steps takes place. If performance is not as good as you expect, you canuse this information to see exactly where the performance hit takes place.Finding a one-second gap between AuthenticateRequest and AuthorizeRequest leadsto a different conclusion than finding a one-second gap from the start ofLoadViewState to the start of LoadPostData. The entire time from BeginRequestto EndRequest is how long ASP.NET spends processing the user?s request; if thisis five seconds, is the time being eaten up in code you write in the Page_Loadevent, or somewhere else?

 

If you are not familiar with the System.Diagnosticstracing classes, I suggest you read up on them. Adding some instructions to theconfiguration section of the web.config file is a good place to start; see Figure2 for an example that defines a trace switch, as well as a text file to outputtrace statements to. Be sure that the folder where the log file should go (?C:\Logs?in Figure 2) exists and that the user account that runs ASP.NET (usually ASPNETfor Windows XP) has rights to this folder; otherwise, you may see a ?ConfigurationError? when you start your application.

 

<configuration>

 ...

 <system.diagnostics>

   <switches>

     <addname="Lifecycle" value="4" /> <!-- Verbose=4 -->

   </switches>

   <traceautoflush="true" indentsize="0">

     <listeners>

       <addname="LifecycleLogFile"

         type="System.Diagnostics.TextWriterTraceListener"

         initializeData="C:\Logs\lifecycle.log"/>

     </listeners>

   </trace>

 </system.diagnostics>

 ...

</configuration>

Figure 2: Avoidconfiguration errors.

 

Some of the lifecycle steps are events, some are methods,and in some cases, both are provided. For the HttpApplication object, we canwrite events for all the steps, but the methods behind the scenes are notexposed. For the Page class on the other hand, all the steps have analogousmethods, but they don?t all have events. Where an event is provided, we canwrite code to be executed when the event fires. For the methods, we need tooverride the method in order to add tracing (we also case the base method fromour override so that everything continues to work correctly).

 

For example, we can add code to the Page_Load event if wewant to add a line of code that will write the date and time to a log fileusing the Trace classes whenever the Page?s Load step takes place. We can alsooverride the OnLoad method, making sure we call base.OnLoad from our OnLoad.

 

Tracing each step enables us to build a timeline of whatsteps took place when. Then we can determine how long each step took, whichwill expose which steps, if any, are suffering from performance issues. Forexample, if the Render step takes two seconds, you?ll know that the problem isthere and not in the Load event. You are now in a much better position to findthe source of the problem than if all that you knew was that the whole requestis taking about two seconds.

 

You?ll need to log very specific information to properlyreconstruct the timeline for each request. An ASP.NET application typically hasmultiple users and, thus, concurrent requests ? you need a way to match entriesin the log file to a particular request, because the steps from differentrequests will be interspersed. Each concurrent request runs on a differentthread, but all the steps of a single request run on the same thread. Thismakes the thread id very useful. Other information, such as the username, theURL of the requested page, and the session id, are also useful. Figure 3 containsan example of a trace statement that logs this information.

 

public static TraceSwitch lifecycleSwitch =

 newTraceSwitch("Lifecycle", "Lifecycle Log");

 

private void Page_Load(object sender, System.EventArgs e)

{

 System.Diagnostics.Trace.WriteLineIf(

  lifecycleSwitch.TraceInfo,string.Format(

    "{0:yyyy-MM-ddHH:mm:ss.ffff}\t{1}\t{2}\t{3}\t{4}\

   t{5}\t{6}\t{7}\t{8}",DateTime.Now, "Page",

   this.GetType().Name,"Page_Load", "Start",

   User.Identity.Name,AppDomain.GetCurrentThreadId(),

   Request.Url.PathAndQuery,Session.SessionID ));

 

 // Put user code toinitialize the page here

 sqlDataAdapter1.Fill(dataSet1);

 DataGrid1.DataBind();

 

 System.Diagnostics.Trace.WriteLineIf(

  lifecycleSwitch.TraceInfo,string.Format(

   "{0:yyyy-MM-ddHH:mm:ss.ffff}\t{1}\t{2}\t{3}\t{4}\

   t{5}\t{6}\t{7}\t{8}",DateTime.Now, "Page",

   this.GetType().Name,"Page_Load", "End",

   User.Identity.Name,AppDomain.GetCurrentThreadId(),

   Request.Url.PathAndQuery, Session.SessionID ));

}

Figure 3: A tracestatement that logs the username, URL of the requested page, and session id.

 

Looking at Figure 3 in detail, you can see that I added atrace statement to the beginning and the end of the Page_Load event, which iscreated by default in Visual Studio when a new ASP.NET page is created. Tracingat the beginning and end of Page_Load allows me to determine how much time isspent in the code that I wrote in that event. Notice that I specified ?System.Diagnostics.Trace?instead of simply ?Trace?. This is necessary even if I reference ?System.Diagnostics?with a using statement because the Page class has a property called Trace thatis used for ASP.NET tracing. ASP.NET tracing is another kind of tracing that isoutside the scope of this article; to learn more about that, see ?ASP.NET Tracing?in the .NET Framework documentation. The tracing I?m using here is referred toas ?System.Diagnostics? tracing.

 

Notice in Figure 3 that I use the WriteLineIf method. Ittakes a boolean as the first parameter and only writes the line if that valueis true. By using the trace switch that was created in Figure 2, tracing can beeasily turned on and off and different levels of logging can be applied simply bychanging the web.config file. The levels and their corresponding values arenothing (0), Error (1), Warning (2), Info (3), and Verbose (4). I find it oddthat you can?t specify the enumeration by name in the web.config file, butmaybe Microsoft will fix that in a future release. I set the value to 4 in Figure2 so that all levels would be output; if you set the value, say, to 2, thenonly the Error and Warning levels would be output. You can create multipleswitches to suit your needs.

 

In the call to WriteLineIf I delimit all the data that Ioutput with tabs; this makes it easier to parse the data later. I output thecurrent date/time, an arbitrary category (I chose ?Page?), the name of the Webform?s class (I get the name using reflection), the name of the step I?m in,whether it is the start or end of the step, the user making the request, the idof the thread I?m in, the requested URL (it may contain more useful informationthan just the name of the Web form?s class), and the current session id (which mayhelp draw together separate requests from the same user?s session).

 

This may seem like a hefty chunk of code to put at thebeginning and end of each event ? especially when you recall all the eventsfrom Figure 1 and consider how many Web forms you may have in your application.Fortunately, there is a more efficient solution than adding this code to allyour forms. All pages that you create using ASP.NET inherit fromSystem.Web.UI.Page by default. We can create a custom class, let?s call itTracingPage, that inherits from the default Page class. Then, we have our pagesinherit from our custom class instead of the default. In TracingPage, all themethods that correspond to each step can be overloaded and the logging can beperformed there. Then, any page in your application can be made to do thetracing simply by having it inherit from TracingPage. Note that I prefer tooverload the methods instead of adding event handlers ? not all the page stepshave events, but we can take care of all the steps by overloading theirrespective methods.

 

Take a look at my TracingPage class in Listing One. I created a method called DoStandardTracethat logs all the information that we need. I made it as generic as possible ?it even retrieves the name of the step that is being logged (such as OnInit)from the stack frame so that it doesn?t need to be passed in (it assumes thatit is being called directly by the method whose name it should log). I thenoverride each of the methods in the Page class that correspond to a step thatshould be logged. In each method, I log the ?start? of the method, call thebase class? implementation of the method, and then log the ?end? of the method.The processing actually occurs when the base class? implementation is called.For example, when base.OnLoad is called, your Page_Load event will get fired.

 

From the sample code (available for download; see end of articlefor details), run WebForm2, which inherits from the TracingPage class. (Note:the sample assumes you have SQL Server and the pubs database installedlocally.) After the page loads, click the button once to cause a post back.Your log file should now look similar to Figure 4. (If you received aconfiguration error, be sure that the output folder for the log file exists.)Notice that the initial page request did not execute the LoadViewState and theRaisePostBackEvent methods, but that the request caused by clicking the buttondid. Also, note how the output looks. The request, for example, is ?/Lifecycle/WebForm2.aspx?,which will also contain any query parameters that may have been included. Thethread id is an integer (on your workstation it may often be the same value,but in a multi-user environment you should see the number change often becausedifferent threads from the pool service different requests). The session id, analphanumeric string, will remain the same for all requests coming from the samebrowser session. Finally, notice that the user name was blank in my example becauseI did not turn on any type of authentication. If you are using WindowsAuthentication, the user name would be in the familiar ?domain\user? format.Logging this sort of information can help you track down problems that usersreport. The session id and user name help you follow the workflow of requestsperformed by a given user.

 

2004-07-18 14:58:14.3101 Page WebForm2_aspx

 OnInit Start 700 / Lifecycle/WebForm2.aspx

 4fpvhuyyvt3zpkfyckw3k4v1

2004-07-18 14:58:14.3201 Page WebForm2_aspx

 OnInit End 700 / Lifecycle/ ...

2004-07-18 14:58:14.3302 Page WebForm2_aspx

 OnLoad Start 700 / Lifecycle/ ...

2004-07-18 14:58:14.4203 Page WebForm2_aspx

 OnLoad End 700 / Lifecycle/ ...

2004-07-18 14:58:14.4203 Page WebForm2_aspx

 OnPreRender Start 700 / Lifecycle/ ...

2004-07-18 14:58:14.4203 Page WebForm2_aspx

 OnPreRender End 700 / Lifecycle/ ...

2004-07-18 14:58:14.4303 Page WebForm2_aspx

 SaveViewState Start 700 / Lifecycle/ ...

2004-07-18 14:58:14.4303 Page WebForm2_aspx

 SaveViewState End 700 / Lifecycle/ ...

2004-07-18 14:58:14.7107 Page WebForm2_aspx

 Render Start 700 / Lifecycle/ ...

2004-07-18 14:58:14.7608 Page WebForm2_aspx

 Render End 700 / Lifecycle/ ...

2004-07-18 14:58:14.7608 Page WebForm2_aspx

 OnUnload Start 700 / Lifecycle/ ...

2004-07-18 14:58:14.7608 Page WebForm2_aspx

 OnUnload End 700 / Lifecycle/ ...

2004-07-18 14:58:14.7608 Page WebForm2_aspx

 Dispose Start 700 / Lifecycle/ ...

2004-07-18 14:58:14.7608 Page WebForm2_aspx

 Dispose End 700 / Lifecycle/ ...

2004-07-18 14:58:23.8238 Page WebForm2_aspx

 OnInit Start 700 / Lifecycle/ ...

2004-07-18 14:58:23.8238 Page WebForm2_aspx

 OnInit End 700 / Lifecycle/ ...

2004-07-18 14:58:23.8438 Page WebForm2_aspx

 LoadViewState Start 700 / Lifecycle/ ...

2004-07-18 14:58:23.8538 Page WebForm2_aspx

 LoadViewState End 700 / Lifecycle/ ...

2004-07-18 14:58:23.8839 Page WebForm2_aspx

 OnLoad Start 700 / Lifecycle/ ...

2004-07-18 14:58:23.8939 Page WebForm2_aspx

 OnLoad End 700 / Lifecycle/ ...

2004-07-18 14:58:23.9039 Page WebForm2_aspx

 RaisePostBackEventStart 700 / Lifecycle/ ...

2004-07-18 14:58:23.9139 Page WebForm2_aspx

 RaisePostBackEventEnd 700 / Lifecycle/ ...

2004-07-18 14:58:23.9240 Page WebForm2_aspx

 OnPreRender Start 700 / Lifecycle/ ...

2004-07-18 14:58:23.9340 Page WebForm2_aspx

 OnPreRender End 700 / Lifecycle/ ...

2004-07-18 14:58:23.9340 Page WebForm2_aspx

 SaveViewState Start 700 / Lifecycle/ ...

2004-07-18 14:58:23.9340 Page WebForm2_aspx

 SaveViewState End 700 / Lifecycle/ ...

2004-07-18 14:58:23.9440 Page WebForm2_aspx

 Render Start 700 / Lifecycle/ ...

2004-07-18 14:58:23.9540 Page WebForm2_aspx

 Render End 700 / Lifecycle/ ...

2004-07-18 14:58:23.9540 Page WebForm2_aspx

 OnUnload Start 700 / Lifecycle/ ...

2004-07-18 14:58:23.9540 Page WebForm2_aspx

 OnUnload End 700 / Lifecycle/ ...

2004-07-18 14:58:23.9540 Page WebForm2_aspx

 Dispose Start 700 / Lifecycle/ ...

2004-07-18 14:58:23.9640 Page WebForm2_aspx

 Dispose End 700 / Lifecycle/ ...

Figure 4: A samplelog file.

 

The TracingPage class takes care of logging what happenedduring page processing. Now it?s time to add some tracing to the global.asaxfile to trace what is happening at the application level. Open the global.asaxfile (Visual Studio 2003 adds it for you by default) and look at the sourcecode. You?ll see that events like Application_BeginRequest already exist,making it easy to add logging to them. The only choice you have here is tohandle events (you can?t override methods like we did in TracingPage). Onlysome of the events have already been added. If you look at global.asax indesign view you can open the properties window and select any event you want tocapture; adding events this way will create new events calledGlobal_[EventName]. However, you can also add additional events with thecorrect Application_[EventName], like the defaults in the file, and they willbe picked up automatically.

 

I?ve added logging for all the application events in thedownloadable code for this article. In Listing Two, youcan see that the code is very similar to that in TracingPage. There is ageneric routine to log the information that we want to capture, and then a callto that routine from each of the events. However, for certain events, some ofthe information will not be available yet, and attempting to access it willthrow an exception. For example, in the Application_Start event, you cannotaccess the Request object, so I pass flags to the DoStandardTrace methodtelling it whether or not to try to log the request and the session (the twotroublemakers).

 

With tracing now in place for both Page andHttpApplication events, I encourage you to experiment with pages in yourexisting ASP.NET applications, and then examine the logs to get a feel for whatkind of data is produced. You can customize the logging to suite your needs.For example, you could create multiple trace switches to change the granularityof what you log. You could create switches for each step, and then configurewhich steps are logged by changing the switch values in web.config.

 

You might also wish to add logging to other importantareas of your application. For example, if you have a data access wrapper, youcould log right before and right after every stored procedure call, enablingyou to analyze database performance in your ASP.NET application. Anywhere thatyour application performs operations where you may want to monitor performanceare potential places to log ? Web services, remoting, third-party APIs, etc.

 

If you are collecting quite a bit of data, as you arelikely to do in a real-world multi-user application, you?ll also need a way toprocess this data so that it is usable. Application_BeginRequest andApplication_EndRequest give you the big picture of how long request processingtook. You could write macros in Excel to import the log file and process thedata ? once you find a BeginRequest, you?ll want to find the matchingEndRequest for the same thread id. You might import the data into SQL Server inorder to process it. You?ll want to match up the Start and End log entries fromeach of the various page steps to calculate how long each step took. Then matchup each of the steps to a request, and group all the data by request, so thatyou can walk through the steps of an individual request.

 

You may run into some nuances when processing the data.Sometimes the Page?s OnUnload method is called twice (this appears to be a bug).Also, if you make use of Response.Redirect or Response.End, you might noticethat some of the steps you were expecting are skipped. Server.Transfer or your owncustom HTTP handlers may also call for special processing. Finally, yourprocessing code will need to pull together data elements from different steps forit to make sense. For example, if you want to summarize data byBeginRequest/EndRequest, you?ll need to find the user, requested URL, andsession ids from other events that took place after BeginRequest (because notall values were known yet).

 

You can use this information to calculate average responsetime for each page, etc. Or, for requests that took ?too long? you can look ateach step to see where the issue is. The processed data can be used for usagestatistics (which users are using which parts of the application?, etc.), forperformance statistics (did that new query optimization make a difference?), orto follow the steps a user apparently took when running into some elusive bugthat was reported.

 

Last spring I deployed a mission-critical tradingapplication. Unfortunately, performance degraded considerably after it was inproduction for a short period of time. I was at a loss as to what the problemcould be, but I had to get it resolved quickly. I began by adding some tracingto check database performance. The problem wasn?t there, so I added sometracing to the page lifecycle, which also appeared to be processing quickly ?at least from OnInit to OnUnload. I had to examine everything that might behappening from the split second that the user clicked a button in the browserto the second that the new page finished rendering in the browser. In the end,several tools came into play. I used a third-party product (HttpWatch) on theuser?s machine to see if there were any delays on the client before and afterthe request to the Web server. I enabled detailed logging in IIS and correlatedwhat IIS thought the request processing time was with ASP.NET and HttpWatch.

 

Lifecycle tracing ended up pointing to a performance hitbeing taken at Application_AuthenticateRequest in the authentication stage. Iused netcap and netmon to capture all network traffic on the Web server andclient. I found that the delay correlated with the Web server communicatingwith a domain controller (DC) at a remote location. Apparently, it wasauthenticating the user against the remote DC when it should have beencommunicating with a DC in the same rack. An active directory configurationissue was identified and resolved. Understanding and logging the completeASP.NET lifecycle was the key to pinpointing and resolving this issue.

 

There are even more lifecycle steps in ASP.NET 2.0 thatyou can use for logging. The Page object adds methods such as OnLoadComplete,and the HttpApplication object expands, adding Pre- and Post- events such asPreAuthenticateRequest and PostAuthenticateRequest instead of onlyAuthenticateRequest. The TracingPage class from this article should get youstarted. If you are using ?partial? pages (the default), simply add theInherits=?TracingPage? attribute to the @Page directive in the aspx file. Also,the documentation specifically includes instructions for usingSystem.Diagnostics tracing and adding it to the web.config file as presentedhere.

 

The sample code forthis article is available for download.

 

Adwait Ullal is anindependent .NET Architect in Saratoga, CA. He has architected systems for suchFortune 100 companies as American Express, JP Morgan Chase, and Visa. ContactAdwait at mailto:adwait.ullal@gmail.comwith questions or comments.

 

Begin Listing One

public class TracingPage : System.Web.UI.Page

{

   public static System.Diagnostics.TraceSwitch

  lifecycleSwitch = newSystem.Diagnostics.TraceSwitch(

  "Lifecycle","Lifecycle Log");

 public const stringSTART_MARKER = "Start";

 public const stringEND_MARKER = "End";

 public string currentPage= null;

 public string currentUser= null;

 public stringcurrentRequest = null;

 public intcurrentThreadId = 0;

 

 protected voidDoStandardTrace(string marker)

 {

   // Use the Stack Frameto determine which method is

   // requesting loggingso that we can log the method

   // name without passingit in.

   System.Diagnostics.StackFrame callingFrame =

     newSystem.Diagnostics.StackTrace().GetFrame(1);

 

   System.Diagnostics.Trace.WriteLineIf(

    lifecycleSwitch.TraceInfo,string.Format(

     "{0:yyyy-MM-ddHH:mm:ss.ffff}\t{1}\t{2}\t{3}\t{4}\

      t{5}\t{6}\t{7}\t{8}",

     System.DateTime.Now,             // timestamp

     "Page",                         // category

     currentPage,                    // Web Form class

     callingFrame.GetMethod().Name,  // step (OnInit, etc.)

     marker,                         // start, end, etc

     currentUser,                    // user name

     currentThreadId,                // current thread id

     currentRequest,                 // URL requested

     Session.SessionID              //session id

     ));

 }

 

 override protected voidOnInit(System.EventArgs e)

 {

   currentPage =this.GetType().Name;

   currentUser =User.Identity.Name;

   currentRequest =Request.Url.PathAndQuery;

   currentThreadId =System.AppDomain.GetCurrentThreadId();

 

   DoStandardTrace(START_MARKER);

   base.OnInit(e);

   DoStandardTrace(END_MARKER);

 }

 

 override protected voidLoadViewState(object savedState)

 {

   DoStandardTrace(START_MARKER);

   base.LoadViewState(savedState);

   DoStandardTrace(END_MARKER);

 }

 

 override protected voidOnLoad(System.EventArgs e)

 {

   DoStandardTrace(START_MARKER);

   base.OnLoad(e);

   DoStandardTrace(END_MARKER);

 }

 

 override protected voidRaisePostBackEvent(

   System.Web.UI.IPostBackEventHandler sourceControl,

     string eventArgument)

 {

   DoStandardTrace(START_MARKER);

   base.RaisePostBackEvent(sourceControl, eventArgument);

   DoStandardTrace(END_MARKER);

 }

 

 override protected voidOnPreRender(System.EventArgs e)

 {

   DoStandardTrace(START_MARKER);

   base.OnPreRender(e);

   DoStandardTrace(END_MARKER);

 }

 

 override protected objectSaveViewState()

 {

   DoStandardTrace(START_MARKER);

   object returnObject =base.SaveViewState();

   DoStandardTrace(END_MARKER);

   return returnObject;

 }

 

 override protected voidRender(

  System.Web.UI.HtmlTextWriterwriter)

 {

   DoStandardTrace(START_MARKER);

   base.Render(writer);

   DoStandardTrace(END_MARKER);

 }

 

 override public voidDispose()

 {

   DoStandardTrace(START_MARKER);

   base.Dispose();

   DoStandardTrace(END_MARKER);

 }

 

 override protected voidOnUnload(System.EventArgs e)

 {

   DoStandardTrace(START_MARKER);

   base.OnUnload(e);

   DoStandardTrace(END_MARKER);

 }

 

}//class TracingPage

End Listing One

 

Begin Listing Two

...

 

public static System.Diagnostics.TraceSwitch

 lifecycleSwitch = newSystem.Diagnostics.TraceSwitch(

 "Lifecycle","Lifecycle Log");

 

protected void DoStandardTrace(bool request, bool session)

{

 // Use the Stack Frame todetermine which method is

 // requesting logging sothat we can log the method

 // name without passingit in.

 System.Diagnostics.StackFrame callingFrame =

   newSystem.Diagnostics.StackTrace().GetFrame(1);

 

 System.Diagnostics.Trace.WriteLineIf(

  lifecycleSwitch.TraceInfo,string.Format(

   "{0:yyyy-MM-ddHH:mm:ss.ffff}\t{1}\t{2}\t{3}\t{4}\

     t{5}\t{6}\t{7}\t{8}",

   System.DateTime.Now,             // time stamp

   "Global",                       // category

   this.GetType().Name,             // Web Form class

   callingFrame.GetMethod().Name,   // step (OnInit, etc.)

   "Event",                         // start, end, etc

    (request &&(User != null)) ?

    User.Identity.Name : null,     // user name

   System.AppDomain.GetCurrentThreadId(

    ),                             // current thread id

   request ?Request.Url.PathAndQuery : null, // URL requested

   session ?Session.SessionID : null        //session id

   ));

}

 

 

protected void Application_Start(Object sender, EventArgs e)

{

 DoStandardTrace(false,false);

}

 

protected void Session_Start(Object sender, EventArgs e)

{

 DoStandardTrace(false,true);

}

 

 

//

// REQUEST EVENTS

//

 

protected void Application_BeginRequest(Object sender,

 EventArgs e)

{

 DoStandardTrace(true,false);

}

 

protected void Application_AuthenticateRequest(Object sender,

 EventArgs e)

{

 DoStandardTrace(true,false);

}

 

protected void Application_AuthorizeRequest(Object sender,

 EventArgs e)

{

 DoStandardTrace(true,false);

}

 

...

End Listing Two

 

 

 

Add a Comment

There are no comments to display. Be the first one!
You must log on before posting a comment.

Are you a new visitor? Register Here

advertisement




Comments from the DevConnections Community

Join our community of development pros.

Windows problem

I all, I have a problem on my Windows Vista that began afetr the purchase of an external Hard Disk Freecom. A few days afetr the purchase I discon...

Most Recent Posts

GOOGLE LINKS
SPONSORED LINKS
FEATURED LINKS