Debugging, Tracing and Instrumentation in .NET and ASP.NET (14 FAQ)
Contents
Diagnosing a software application is an art and this art has to be more skillful when you go on production.
In development environment you have the complete VS IDE tool so the diagnosing becomes much easier. On production environment as a best practice you do not install visual studio IDE. So on production it’s like fighting with the lion without a knife.
This article has a three point agenda.
• We will first start with understanding some basic vocabularies like debug, trace and instrumentation.
• Once we understand the vocabularies we will see how to use the trace attribute to tracing in ASP.NET. We will also understand some drawbacks of the same.
• We will then try to remove those drawbacks using the full tracing framework which comes as a part of “system.diagnostic” namespace. In tracing framework we will try to understand trace object , switches and listeners.
You can watch my
.NET interview questions videos on various sections like WCF, Silver light, LINQ, WPF, Design patterns, Entity framework etc.
Debugging application is not just about pressing F 10 or F 11 and watching “add watch windows” using visual studio IDE. Debugging becomes pretty complex on production environments where the project is deployed in a release mode and you need to figure out till what point the code ran and when did it crash. The worst part is you are enjoying your sleep at home and suddenly someone calls up and says, “Hey! the application crashed in production”.
If your application is well planned with proper instrumentation you can just say the person to view the event viewer or a log file for further details and you can give the solution on the phone itself.
So defining instrumentation in short, it’s the ability of the application to monitor execution path at critical points to do debugging and measure performance.
We would like to enable application instrumentation in two situations while you are doing development and while your application is in production. When you monitor application execution and performance in development stage is termed as “Debugging” and when you do in deployed environment it’s termed as ‘Tracing’.
Debugging and tracing can be implemented by importing ‘System.Diagnostic’ namespace and by calling ‘Debug’and ‘Trace’ methods as shown in the below code. In the below code we are tracking critical execution points like page load and button click.
protected void Page_Load(object sender, EventArgs e)
{
Debug.Write("Debug :- The page is loaded\n");
Trace.Write("Trace :- The page is loaded\n");
}
protected void Button1_Click(object sender, EventArgs e)
{
Debug.Write("Debug :- Button is clicked\n");
Trace.Write("Trace :- Button is clicked\n");
}
As said previously debug is meant for enabling instrumentation in development phase while tracing helps during execution. During development VS IDE tool is the best medium of viewing debug information and during execution the mediums can be a browser, event viewers, file system etc.
In order to see debug information execute the project, click on debug, windows and click on output menu as shown in the below figure.
You should be able to see the output information in output windows as shown in the below figure.
As debug code is not shipped in production you will not be able to see the debug information while your application is go live. As said previously tracing information is seen when you execute the project in production mode or go live mode. Tracing information can be viewed by on various mediums:-
• By the user interface ( Web browser or the windows UI)
• Event viewer
• Log file, format can be XML, CSV etc.
• In ASP.NET you can also view by using Trace.axd
A quick and dirty way of seeing tracing information is by going to the ASPX front code and put trace=true in the ‘Page’ attribute.
<%@ Page Language="C#" AutoEventWireup="true" trace="true"
CodeBehind="Default.aspx.cs" Inherits="WebTracing._Default" %>
Once you have done the same you should be able to see tracing information as shown in the below figure. With trace enabled as true it also displays lot of other things like different page events , session data , hidden field data , http headers etc. I have circled the custom information which we have written using the ‘Trace’ object.
If you want to enable tracing in all pages, you need to enable trace in the ‘web.config’ file as shown in the below code snippet.
<system.web>
<trace enabled="true" pageOutput="true" requestLimit="40" localOnly="false"/>
</system.web>
In actual production it will not be a good idea to enable the trace using the above two methodologies as the end user can view your tracing information on the browser. So the next logical question is how we silently trace the same.
In order to background silent tracing we need to go to the web.config file and in the trace tag enter pageoutput=false. By setting “pageoutput” to false we say the trace engines do not send messages to browser and collect them in memory.
<system.web>
<trace enabled="true" pageOutput="false" requestLimit="40"
localOnly="false"/>
</system.web>
This in memory stored instrumentation data can be viewed using Trace.axd by typing url
http://localhost:2281/Trace.axd . Below is a sample screen shot which shows how the data looks. If you click on the view details you can see the tracing information.
When we instrument using debug attribute either using page or AXD extension they are not persisted. In other words they are displayed on the browser temporarily.
Most of the times we would like to persist the information in a file, event viewer etc so that we can later see the history for proper diagnosis.
We need to enable the ‘writetoDiagnosticsTrace’ attribute to true. When this attribute is set to true the information is sent to a listener.
<trace enabled="true" requestLimit="10" localOnly="false"
writeToDiagnosticsTrace="true" pageOutput="false"/>
You can then define various types of listeners like text file listener, event viewer etc. Below is a sample code snippet of how the listeners actually look. So the ASP.NET tracing engine will emit diagnosis information which will be then caught and routed to the proper source by the listener.
<system.diagnostics>
<trace autoflush="true">
<listeners>
<clear/>
<add name="textwriterListener" type="System.Diagnostics.TextWriterTraceListener"
initializeData="c:\outfile.txt" traceOutputOptions="ProcessId, DateTime"/>
</listeners>
</trace>
</system.diagnostics>
Below is a simple snapshot of how instrumented data is captured.
When we use the trace attribute it emits out all the events of the page. Sometimes these events can hinder your diagnosis.
If you want to eliminate all ASP.NET events and just concentrate on your message then we need to add a source. We need to then write the messages on the source and the source will redirect the same to the trace listeners.
In order to define a source go to your web.config and in the “system.diagnostics’ tag enter the “source’ tag as shown in the below code snippet. In the below code snippet we have defined the source name as “myTraceSource”. Inside the source we can define variouslisteners.
<system.diagnostics>
<sources>
<source name="myTraceSource" switchName="mySwitch"
switchType="System.Diagnostics.SourceSwitch">
<listeners>
<!-… Define all your listeners in this place ..>
</listeners>
</source>
</sources>
</system.diagnostics>
Below is a complete sample code snippet with listeners defined inside the source.
<system.diagnostics>
<sources>
<source name="myTraceSource" switchName="mySwitch"
switchType="System.Diagnostics.SourceSwitch">
<listeners>
<clear/>
<add name="textwriterListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="c:\outfile.txt" traceOutputOptions="ProcessId, DateTime"/>
</listeners>
</source>
</sources>
</system.diagnostics>
In order to send messages to the trace source using C# code first we need to import namespace “System.Diagnostics” as shown in the below code snippet.
using System.Diagnostics;
Once the namespace is imported we can then send messages on any event by creating the “TraceSource” object and calling “TraceEvent” as shown in the below code snippet.
TraceSource obj = new TraceSource("myTraceSource");
obj.TraceEvent(TraceEventType.Error, 0, "This is a error message");
obj.Close();
It’s the same way define the source and listeners in your app.config file, create the tracesource object and call traceevent method to write the same to the listeners.
We would like to emit different kind of messages from the application like critical messages, error message or just information. The types of messages can be defined by using “TraceEventType” enum as shown in the below code snippet.
obj.TraceEvent(TraceEventType.Critical, 0, "This is a critical message");
obj.TraceEvent(TraceEventType.Warning, 0, "This is a simple warning message");
obj.TraceEvent(TraceEventType.Error, 0, "This is a error message");
obj.TraceEvent(TraceEventType.Information, 0, "Simple information message");
obj.TraceEvent(TraceEventType.Verbose, 0, "Detail Verbose message");
Sometime we would like to control the kind of diagnosis information we see. This can be achieved by using the switch tag in config file.
<system.diagnostics>
....
....
....
<switches>
<add name="mySwitch" value="1"/>
</switches>
</system.diagnostics>
You can define various values depending on what kind of diagnose information you want to record.
You can then attach the switch to the source.
<source name="myTraceSource" switchName="mySwitch"
switchType="System.Diagnostics.SourceSwitch">
Set the switch value to zero.
Summarizing ASP.Net or windows application emits tracing information to the trace source; these messages can be controlled by switches and sent to various sources (file, event viewer, xml etc) which are defined using trace listeners. Below figure summarizes the complete
tracing framework visually.