Creating Trace Listeners in .Net

Introduction

Trace sources are a new feature in the .NET Framework version 2.0 that provides an enhanced tracing system. The basic premise is unchanged: tracing messages are sent through switches to listeners, which report the data to an associated output medium.

A primary difference for version 2.0 is that traces can be initiated through instances of the TraceSource class. TraceSource is intended to function as an enhanced tracing system and can be used in place of the static methods of the older Trace and Debug tracing classes. The familiar Trace and Debug classes still exist, but the recommended practice is to use the TraceSource class for tracing.

One of the most useful debugging features of .Net Framework is Trace type. Form the functionality prospective, “Trace” type is very similar to “Debug” type, but unlike the Debug which is supposed to be used only

during debugging sessions, Trace functions can be compiled into program and shipped to customers, so in case your users encounter a problem, they can activate trace by simply editing applciation configuration file.

Create and Initialize Trace Listeners

The System.Diagnostics.Debug and System.Diagnostics.Trace classes send messages to objects called listeners that receive and process these messages. One such listener, the System.Diagnostics.DefaultTraceListener, is automatically created and initialized when tracing or debugging is enabled.  If you want Trace or Debug output to be directed to any additional sources, you must create and initialize additional trace listeners.

The listeners you create should reflect your application’s needs. For example, if you want a text record of all trace output, create a TextWriterTraceListener listener, which writes all output to a new text file when it is enabled. On the other hand, if you want to view output only during application execution, create a ConsoleTraceListener listener, which directs all output to a console window. The EventLogTraceListener can direct trace output to an event log. For more information, see Trace Listeners.

NOTE

You can create trace listeners in an application configuration file or in your code. We recommend the use of application configuration files, because they let you add, modify, or remove trace listeners without having to change your code.

The following are the steps to create and use a trace listener by using a configuration file:

1- Declare your trace listener in your application configuration file. If the listener you are creating requires any other objects, declare them as well.

The following example shows how to create a listener called myListener that writes to the text file TextWriterOutput.log:

EX.

<configuration>

<system.diagnostics>

<trace autoflush=”false” indentsize=”4″>

<listeners>

<add name=”myListener” type=”System.Diagnostics.TextWriterTraceListener” initializeData=”TextWriterOutput.log” />

<remove name=”Default” />

</listeners>

</trace>

</system.diagnostics>

</configuration>

2- Use the Trace class in your code to write a message to the trace listeners:

EX.

Trace.TraceInformation(“Test message.”);

// You must close or flush the trace to empty the output buffer.

Trace.Flush();

To create and use a trace listener in code

  • Add the trace listener to the Listeners collection and send trace information to the listeners.

EX.

Trace.Listeners.Add(new TextWriterTraceListener(“TextWriterOutput.log”, “myListener”));

Trace.TraceInformation(“Test message.”);

// You must close or flush the trace to empty the output buffer.

Trace.Flush();

  • If you do not want your listener to receive trace output, do not add it to the Listeners collection. You can emit output through a listener independent of the Listeners collection by calling the listener’s own output methods. The following example shows how to write a line to a listener that is not in the Listeners collection.

EX.

TextWriterTraceListener myListener = new TextWriterTraceListener(“TextWriterOutput.log”, “myListener”);

myListener.WriteLine(“Test message.”);

// You must close or flush the trace listener to empty the output buffer.

myListener.Flush();

EX.

The following example shows some of the basic trace features.

Trace.Assert(true, “Assertion that should not appear”);

Trace.Assert(false, “Assertion that should appear “);

Trace.WriteLine(123, “Category 1”);

Trace.WriteLineIf(true, 456, “Category 2”);

Trace.WriteLineIf(false, 789, “Category 3 (should not appear)”);

The real power of Trace and Debug types is in so called trace listeners – trace information subscribers. You can define unlimited number of listeners, and as soon as you add them to trace listener collection, they will start receiving trace messages.

.NET Framework comes with three ready-made listeners: “DefaultTraceListener”, “EventLogTraceListener” and “TextWriterTraceListener” (all in System.Diagnostics namespace).

  • DefaultTraceListener wraps traditional OutputDebugString API,
  • EventLogTraceListener logs messages to Windows Event Log, and
  • TextWriterTraceListener forwards them to a text file.

EX.

The code below demonstrates how to forward trace messages to a text file

TextWriterTraceListener listener = new TextWriterTraceListener(“MyTrace.txt”);

Trace.AutoFlush = true;

Trace.Listeners.Add(listener);

Trace.WriteLine(123, “Category 1”);

NOTE

  • Defining trace output path in your source code is pretty bad idea and serves only demonstration purposes. Trace listener parameters can (and should) be specified in application configuration file.
  • Although three built-in .NET trace listeners cover pretty much of what developers would expect from trace facility, sometimes you will need more. A good programming exercise can be implementation of DatabaseTraceListener that will forward messages to a database.

However, I suppose that most of developers use text files as primary means of storing intermediate program states (unless you expect your customers to configure SQL database in order to collect your program trace output).

Instrumentation and Tracing

The term instrumentation refers to an ability to monitor or measure the level of a product’s performance and to diagnose errors. In programming, this means the ability of an application to incorporate:

  • Code tracing – Receiving informative messages about the execution of an application at run time.
  • Debugging – Tracking down and fixing programming errors in an application under development.
  • Performance counters – Components that allow you to track the performance of your application.
  • Event logs – Components that allow you receive and track major events in the execution of your application.

The Trace and Debug classes provide the means to monitor and examine application performance eaither during development or after deployment. For example, you can use te Trace class to track particular types

of actions in a deployed application as they occur, and can therefor monitor the application’s efficiency.

During development, you can use the output methods of the Debug class to display messages in the Output window of the Visual Studio integrated development environment (IDE).

There are three phases of code tracing:

 

  • Instrumentation — you add trace code to your application.
  • Tracing — the tracing code writes information to the specified target.
  • Analysis — you evaluate the tracing information to identify and understand problems in the application.

During development, all debug and trace output methods write information to the Output window in Visual Studio by default. In a deployed application,

the methods write tracing information to the targets you specify.

Trace output is collected by objects called Listeners. A listener is an object that receives trace output and writes it to an ouput device (Usually a Window, log or text file). When a trace listener is created, it is typically added to the Trace.Listeners collection, allowing the listener to receive all trace ouput.

Tracing information is always written at least to the default Trace output target, the DefaultTraceListener. If for some reason you have deleted the DefaultTraceListener without adding any other listeners to the Listeners collection, you will not receive any tracing messages.

EX.

System.Diagnostics.Trace.WriteLine(“Hello World!”);

System.Diagnostics.Debug.WriteLine(“Hello World!”);

Each of these examples will display “Hello World!” in the Output window when the application is run in the debugger.

This enables you to debug your applications and optimize their performance based on their behavior in your test envrionment.

The Microsoft .NET Framework comes with powerful, extensible classes for debugging and tracing applications. For instance, one of the most useful debugging techniques is to log the progress of an application as it executes.

This lets you identify where in your code the application is when problems occur. This technique is generally faster than running programs through the debugger. Before .NET, most C++ programmers used printf() to log messages to a console window while the application ran.

When a debugger was available, TRACE() and other macros were used to send messages directly to the debugger’s output window. In .NET, you can use these same techniques through trace listeners exposed by the Framework.

A trace listener is a class that listens for trace and debug messages from .NET applications. Most trace listeners display messages to users through a text box or by writing messages to files. Trace listeners can modify messages before displaying them, or even filter out messages if it wishes.

Trace listeners derive from the System.Diagnostics.TraceListener base class. This abstract base class provides the interface and base functionality that all trace listeners expose.

The .NET Framework ships with three trace listeners:

 

  • EventLogTraceListener for logging messages to event logs.
  • DefaultTraceListener for logging messages to standard debug output such as debuggers.
  • TextWriterTraceListener for logging messages to text files.

NOTE

  • These predefined trace listeners cover the common cases but you can also define your own.

The .NET Framework comes with powerful, extensible classes for debugging and tracing applications, the following table shows some of these methods that are used in tracing information:

Member

Description

Close() Closes the listener. Further messages are ignored.
Flush() Flushes all messages to the output.
IndentLevel Gets or sets the indentation level of the messages.
IndentSize Gets or sets the size of an indentation.
Write() Writes a message to the listener but does not continue to the next line.
WriteLine() Writes a message to the listener and moves to the next line.
Assert() The specified text, or if none is specified, the Call Stack.
Trace Class is written only if the condition specified as an argument in the Assert statement is false.
Fail() The specified text, or if none is specified the Call Stack.
WriteIf() The specified text, if the condition specified as an argument in the WriteIF statement is satified.

 Trace Class

Namespace: System.Diagnostics

Provides a set of methods and properties that help you trace the execution of your code. This class cannot be inherited.

You can use the properties and methods in the Trace class to instrument release builds. Instrumentation allows you to monitor the health of your application running in real-life settings. Tracing helps you isolate problems and fix them without disturbing a running system.

You can customize the tracing output’s target by adding TraceListener instances to or removing instances from the Listeners collection.The Listeners collection is shared by both the Debug and the Trace classes; adding a trace listener to either class adds the listener to both.

NOTE

  • Adding a trace listener to the Listeners collection can cause exception to be thrown while tracing, if a resource used by the trace listener is not available.It may be useful to place calls to te Trace methods in try/catch blocks to detect and handle any exceptions from trace listeners.
  • The Trace class provides properties to get or set the level of Indent, the IndentSize, and whther to AutoFlush after each write. To set the AutoFlush and IndentSize for Trace, you can edit the configuration file that corresponds to the name of your application. The configuration file should be formatted as follows:

<configuration>

<system.diagnostics>

<trace autoflush=”false” indentsize=”3″ />

</system.diagnostics>

</configuration>

EX.

// Specify /d:TRACE when compiling.

// The following example will use the Console Output as a trace listener

using System;

using System.Diagnostics;

class Test

{

static void Main()

{

Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));

Trace.AutoFlush = true;

Trace.Indent();

Trace.WriteLine(“Entering Main”);

Console.WriteLine(“Hello World.”);

Trace.WriteLine(“Exiting Main”);

Trace.Unindent();

}

}

Traces are the publishing of specific messages that are generated during application execution. When using tracing, you must have a mechanism for collecting and recording the messages that are sent. Trace messages are received by listeners. The purpose of a listener is to collect, store, and route tracing messages. Listeners direct the tracing output to  an appropriate target, such as a log, window, or text file.

One such listener, the DefaultTraceListener, is automatically created and initialized when tracing is enabled.  If you want trace output to be directed to any additional sources,  you must create and initialize additional trace listeners. The listeners you create should reflect your individual needs. For example, you might want a text record of all trace output. In this case, you would create a listener that wrote all output to a new text file when enabled. On the other hand, you might only want to view output during application execution. In that case, you might create a listener that directed all output to a console window. The EventLogTraceListener can direct trace output to an event log, and the TextWriterTraceListener can write trace output to a stream.

Enable Tracing

 To enable traces during transaction processing, you should edit your application’s configuration file.

EX.

In the following example the “System.Transactions” traces are written to the source named “System.Transactions”. You can use add to specify the name and type of the trace listener you want to use.

In our example configuration, we named the Listener “tx” and added the standard .NET Framework trace listener (XmlWriterTraceListener) as the type we want to use.

Use initializeData to set the name of the log file for that listener. In addition, you can substitute a fully qualified path for a simple file name.

<configuration>

<system.diagnostics>

<sources>

<source name=”System.Transactions” switchValue=”Warning”>

<listeners>

<add name=”tx”

type=”System.Diagnostics.XmlWriterTraceListener”

initializeData= “tx.log” />

</listeners>

</source>

</sources>

</system.diagnostics>

</configuration>

Each trace message type is assigned a level to indicate its degree of importance. If the app-domain’s trace level is equal or lower than the level of an event type, then that message is generated. The tracing level is controlled by the switchValue setting in the configuration file. The levels that are associated with diagnostic trace messages are defined in the following table.

Trace Level

Description

Critical Serious failures, such as the following, have occurred:

  • An error that can cause an immediate loss in user functionality.
  • An event that requires an administrator to take action to avoid loss of functionality.
  • This tracing level can also provide sufficient context for interpreting other critical traces. This can help to identify the sequence of operations leading to a serious failure.

 

Error An error (for example, invalid configuration or network behavior) has occurred that can result in a loss of user functionality. 
Warning          A condition exists that can subsequently result in an error or critical failure (for example, allocation failing or approaching a limit). Normal processing of errors from user code (for example, transaction aborted, timeouts, authentication failed) can also generate a warning.
Information Messages helpful for monitoring and diagnosing system status, measuring performance, or profiling are generated. These can include transaction and enlistment lifetime events, such as a transaction being created or committed, the crossing of a significant boundary, or the allocation of significant resources. A developer can then utilize such information for capacity planning and performance management.

When using Trace, Debug and TraceSource, you must have a mechanism for collecting and recording the messages that are sent. Trace messages are received by listeners. The purpose of a listener is to collect, store, and route tracing messages.

Listeners direct the tracing output to an appropriate target, such as a log, window, or text file.

Listeners are available to the Debug, Trace, and TraceSource classes, each of which can send its output to a variety of listener objects. The following are the commonly used predefined listeners:

 

  • A TextWriterTraceListener= redirects output to an instance of the TextWriter class or to anything that is a Stream class. It can also write to the console or to a file, because these are Stream classes.
  • An EventLogTraceListener= redirects output to an event log.
  • A DefaultTraceListener= emits Write and WriteLine messages to the OutputDebugString and to the Debugger.Log method. In Visual Studio, this causes the debugging messages to appear in the Output window.

Fail and failed Assert messages also emit to the OutputDebugString Windows API

and the Debugger.Log method, and also cause a message box to be displayed.

This behavior is the default behavior  for Debug and Trace messages, because

DefaultTraceListener is automatically included in every Listeners collection and is

the only listener automatically included.

  • A ConsoleTraceListener= directs tracing or debugging output to either the standard output or the standard error stream.
  • A DelimitedListTraceListener= directs tracing or debugging output to a text writer, such as a stream writer, or to a stream, such as a file stream. The trace output is in a delimited text format that uses the delimiter specified by the Delimiter property.
  • An XmlWriterTraceListener= directs tracing or debugging output as XML-encoded data to a TextWriter or to a Stream, such as a FileStream.

NOTE

  • If you want any listener besides the DefaultTraceListener to receive Debug, Trace and TraceSource output, you must add it to the Listeners collection.
  • Any listener in the Listeners collection gets the same messages from the trace output methods. For example, suppose you set up two listeners: a TextWriterTraceListener and an EventLogTraceListener.  Each listener receives the same message. The TextWriterTraceListener would direct its output to a stream, and the EventLogTraceListener would direct its output to an event log.

Writing a trace to Windows Event Log

App.config

<?xml version=”1.0″ encoding=”utf-8″ ?>

<configuration>

<system.diagnostics>

<trace autoflush=”false” indentsize=”4″>

<listeners>

<add name=”myListener”

type=”System.Diagnostics.EventLogTraceListener”

initializeData=”TraceListenerLog” />

</listeners>

</trace>

</system.diagnostics>

</configuration>

EX.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Diagnostics;

namespace TraceListenerApp4

{

class Program

{

static void Main(string[] args)

{

             // Create a trace listener for the event log.

EventLogTraceListener myTraceListener = new EventLogTraceListener(“myEventLogSource”);

// Add the event log trace listener to the collection.

Trace.Listeners.Add(myTraceListener);

// Write output to the event log.

Trace.WriteLine(“Test output”);

}

}

}

 

Writing a trace to a file

using System;

using System.Diagnostics;

using System.Threading;

namespace TraceSourceApp

{

class Program

{

private static TraceSource mySource =

new TraceSource(“TraceSourceApp”);

static void Main(string[] args)

{

mySource.Switch = new SourceSwitch(“sourceSwitch”, “Error”);

mySource.Listeners.Remove(“Default”);

TextWriterTraceListener textListener =

new TextWriterTraceListener(“myListener.log”);

ConsoleTraceListener console =

new ConsoleTraceListener(false);

console.Filter =

new EventTypeFilter(SourceLevels.Information);

console.Name = “console”;

textListener.Filter =

new EventTypeFilter(SourceLevels.Error);

mySource.Listeners.Add(console);

mySource.Listeners.Add(textListener);

Activity1();

// Allow the trace source to send messages to 

// listeners for all event types. Currently only 

// error messages or higher go to the listeners.

// Messages must get past the source switch to 

// get to the listeners, regardless of the settings 

// for the listeners.

mySource.Switch.Level = SourceLevels.All;

// Set the filter settings for the 

// console trace listener.

mySource.Listeners[“console”].Filter =

new EventTypeFilter(SourceLevels.Critical);

Activity2();

// Change the filter settings for the console trace listener.

mySource.Listeners[“console”].Filter =

new EventTypeFilter(SourceLevels.Information);

Activity3();

mySource.Close();

return;

}

static void Activity1()

{

mySource.TraceEvent(TraceEventType.Error, 1,

“Error message.”);

mySource.TraceEvent(TraceEventType.Warning, 2,

“Warning message.”);

}

static void Activity2()

{

mySource.TraceEvent(TraceEventType.Critical, 3,

“Critical message.”);

mySource.TraceInformation(“Informational message.”);

}

static void Activity3()

{

mySource.TraceEvent(TraceEventType.Error, 4,

“Error message.”);

mySource.TraceInformation(“Informational message.”);

}

}

}

Writing a trace to the Consol Window

 App.Config

<?xml version=”1.0″ encoding=”utf-8″ ?>

<configuration>

<system.diagnostics>

<sources>

<source name=”TraceSourceApp”

switchName=”sourceSwitch”

switchType=”System.Diagnostics.SourceSwitch”>

<listeners>

<add name=”console”

type=”System.Diagnostics.ConsoleTraceListener”>

<filter type=”System.Diagnostics.EventTypeFilter”

initializeData=”Warning”/>

</add>

<add name=”myListener”/>

<remove name=”Default”/>

</listeners>

</source>

</sources>

<switches>

<add name=”sourceSwitch” value=”Warning”/>

</switches>

<sharedListeners>

<add name=”myListener”

type=”System.Diagnostics.TextWriterTraceListener”

initializeData=”myListener.log”>

<filter type=”System.Diagnostics.EventTypeFilter”

initializeData=”Error”/>

</add>

</sharedListeners>

</system.diagnostics>

</configuration>

EX.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Diagnostics;

namespace TraceSourceApp

{

class Program

{

private static TraceSource mySource =

new TraceSource(“TraceSourceApp”);

static void Main(string[] args)

{

Activity1();

mySource.Close();

return;

}

static void Activity1()

{

mySource.TraceEvent(TraceEventType.Error, 1,

“Error message.”);

mySource.TraceEvent(TraceEventType.Warning, 2,

“Warning message.”);

}

}

}

Writing Custom .Net Trace Listeners

The following are the responsibilities among the Trace objects:

-“Trace object”-  decides if the message is going to be sent to listeners and who’s going to receive it. Since this type is sealed, you don’t have much control of this part;

-“TraceListener” receives trace message, optionally add extra formatting (indentation) and writes data using StreamWriter object;

-“StreamWriter” renders lines and single items into a byte stream using specified (or default) encoding and cultural settings;

-Finally, “Stream” is a final destination of trace messages; it does not deal with messages or even lines directly, it obtains only sequences of bytes.

What type should you overrid to implement custom trace listener

 

  • Do not try to come up with your own MyTrace class. Debug and Trace are sealed for good reasons: you don’t have control over standard .NET and third-party types, and they all use built-in Debug and Trace.
  • If you need to apply general message formatting that should be common for all listeners, you only need to convert trace messages into a new format, no changes need to be done to listeners.
  • Override TraceListener if your will apply additional message formatting that is only relevant for this listener. For example, you can extend TextWriterTraceListener functionality by attaching timestamp information to every message (we will show how to do it later in this article). This does not make sense for EventLogTraceListener where timestamp is managed by Event Log itself.
  • Override StreamWriter or Stream types if you need to change the way information is rendered to media. For example, your custom streamer can limit the size of a trace file and backup old data (we will also show how to implement it).

Problem with default Trace Listener

Default trace listener implementation is not really suitable for service applications that are supposed to be always active. If application produces a lot of trace output, then sooner or later this information will use up all disk space.  Even if this does not happen, you will have to deal with huge files that are difficult to manage. In addition, default text trace listener does not store timestamp information with trace messages, so it is impossible to identify exact time when the message was sent.

To solve this problem, we will implement a new type (derived from FileStream) that will take care of trace file and automatically back it up and reset. Our custom FileStream object will be generating a collection of trace files instead of just one:

-MyTrace.txt (recent trace information);

-MyTrace00.txt (trace history backup);

-MyTrace01.txt (trace history backup);

-and so on…

In addition to standard FileStream parameters, our class will require the following initialization data:

Maximum file length = Controls at wat size file is split (and backed up).

Maximum number of backup files = How many backup files can be created. When the maximum number of files is reached, file indext is rest, and backup files are overwritten beginning from the oldest one.

-Boolean switch = Specifies if data that is sent to a stream can be split between different

files within a single Write call. This parameter makes it possible

to keep data integrity (for example, to avoid breaking text lines), if

data that is sent to a stream with Write call must be stored in a single

file, then in case data won’t fit, the file is backed up and reset before

the write operation is performed.

Create and Initialize Trace Source

The TraceSource class is used by applications to produce traces that can be associated with the application. TraceSource provides tracing methods that allow you to easily trace events, trace data, and issue informational traces.

Trace output from TraceSource can be created and initialized with or without the use of configuration files.

1-Create a Visual Studio console application project and replace the supplied code with the following code.

EX.

using System;

using System.Diagnostics;

class TraceTest

{

     private static TraceSource mySource =

new TraceSource(“TraceSourceApp”);

static void Main(string[] args)

{

// Issue an error and a warning message. Only the error message

// should be logged.

Activity1();

// Save the original settings from the configuration file.

EventTypeFilter configFilter =

(EventTypeFilter)mySource.Listeners[“console”].Filter;

// Create a new event type filter that ensures 

// warning messages will be written.

mySource.Listeners[“console”].Filter =

new EventTypeFilter(SourceLevels.Warning);

// Allow the trace source to send messages to listeners 

// for all event types. This statement will override 

// any settings in the configuration file.

// If you do not change the switch level, the event filter

// changes have no effect.

mySource.Switch.Level = SourceLevels.All;

// Issue a warning and a critical message. Both should be logged.

Activity2();

// Restore the original filter settings.

mySource.Listeners[“console”].Filter = configFilter;

Activity3();

mySource.Close();

return;

}

static void Activity1()

{

mySource.TraceEvent(TraceEventType.Error, 1,

“Error message.”);

mySource.TraceEvent(TraceEventType.Warning, 2,

“Warning message.”);

}

static void Activity2()

{

mySource.TraceEvent(TraceEventType.Critical, 3,

“Critical message.”);

mySource.TraceEvent(TraceEventType.Warning, 2,

“Warning message.”);

}

static void Activity3()

{

mySource.TraceEvent(TraceEventType.Error, 4,

“Error message.”);

mySource.TraceInformation(“Informational message.”);

}

}

2- Add an application configuration file and Replace the default configuration file content with the following settings to initialize a console trace listener and a text writer trace listener for the trace source that was created in step 1.

EX.

<configuration>

<system.diagnostics>

<sources>

<source name=”TraceSourceApp”

switchName=”sourceSwitch”

switchType=”System.Diagnostics.SourceSwitch”>

<listeners>

<add name=”console”

type=”System.Diagnostics.ConsoleTraceListener”>

<filter type=”System.Diagnostics.EventTypeFilter”

initializeData=”Error”/>

</add>

<add name=”myListener”/>

<remove name=”Default”/>

</listeners>

</source>

</sources>

<switches>

<add name=”sourceSwitch” value=”Error”/>

</switches>

<sharedListeners>

<add name=”myListener”

type=”System.Diagnostics.TextWriterTraceListener”

initializeData=”myListener.log”>

<filter type=”System.Diagnostics.EventTypeFilter”

initializeData=”Error”/>

</add>

</sharedListeners>

</system.diagnostics>

</configuration>

NOTE

  • In addition to configuring the trace listeners, the configuration file creates filters for both listeners and creates a source switch for the trace source. Two techniques are shown for adding trace listeners: adding the listener directly to the trace source and adding a listener to the shared listeners collection and then adding it by name to the trace source. The filters identified for the two listeners are initialized with different source levels. This results in some messages being written by only one of the two listeners.
  • The configuration file initializes the settings for the trace source at the time the application is initialized. The application can dynamically change the properties set by the configuration file to override any settings specified by the user.  For example, you might want to ensure that critical messages are always sent to a text file, regardless of the current configuration settings. The example code demonstrates how to override configuration file settings to ensure that critical messages are output to the trace listeners.
  • Changing the configuration file settings while the application is executing does not change the initial settings. To change the settings, you must either restart the application or programmatically refresh the application by using the Trace.Refresh method.

To initialize trace sources, listeners, and filters without a configuration file

Use the following example code to enable tracing through a trace source without using a configuration file. This is not a recommended practice, but there may be circumstances in which you do not want to depend on configuration files to ensure tracing.

EX.

using System;

using System.Diagnostics;

using System.Threading;

namespace TraceSourceApp

{

class Program

{

private static TraceSource mySource =

new TraceSource(“TraceSourceApp”);

static void Main(string[] args)

{

mySource.Switch = new SourceSwitch(“sourceSwitch”, “Error”);

mySource.Listeners.Remove(“Default”);

TextWriterTraceListener textListener =

new TextWriterTraceListener(“myListener.log”);

ConsoleTraceListener console =

new ConsoleTraceListener(false);

console.Filter =

new EventTypeFilter(SourceLevels.Information);

console.Name = “console”;

textListener.Filter =

new EventTypeFilter(SourceLevels.Error);

mySource.Listeners.Add(console);

mySource.Listeners.Add(textListener);

Activity1();

// Allow the trace source to send messages to 

// listeners for all event types. Currently only 

// error messages or higher go to the listeners.

// Messages must get past the source switch to 

// get to the listeners, regardless of the settings 

// for the listeners.

mySource.Switch.Level = SourceLevels.All;

// Set the filter settings for the 

// console trace listener.

mySource.Listeners[“console”].Filter =

new EventTypeFilter(SourceLevels.Critical);

Activity2();

// Change the filter settings for the console trace listener.

mySource.Listeners[“console”].Filter =

new EventTypeFilter(SourceLevels.Information);

Activity3();

mySource.Close();

return;

}

static void Activity1()

{

mySource.TraceEvent(TraceEventType.Error, 1,

“Error message.”);

mySource.TraceEvent(TraceEventType.Warning, 2,

“Warning message.”);

}

static void Activity2()

{

mySource.TraceEvent(TraceEventType.Critical, 3,

“Critical message.”);

mySource.TraceInformation(“Informational message.”);

}

static void Activity3()

{

mySource.TraceEvent(TraceEventType.Error, 4,

“Error message.”);

mySource.TraceInformation(“Informational message.”);

}

}

}

EX.

The following example creates a ConsoleTraceListener that outputs to the console screen. The code then adds the new listener to the Listeners.

/* Create a ConsoleTraceListener and add it to the trace listeners. */

ConsoleTraceListener myWriter = new ConsoleTraceListener();

Trace.Listeners.Add(myWriter);

TraceSource Class

Provides a set of methods and properties that enable applications to trace the execution of code and associate trace messages with their source.

TraceSource provides tracing methods that allow you to easily trace events, trace data, and issue informational traces. Trace output from TraceSource can be controlled by configuration file settings.

The configuration file can be used to determine where the trace information is to be sent and what levels of activity are to be traced. The following example shows the contents of a sample application configuration file:

EX.

<configuration>

<system.diagnostics>

<sources>

<source name=”TraceTest” switchName=”SourceSwitch”

switchType=”System.Diagnostics.SourceSwitch” >

<listeners>

<add name=”console” />

<remove name =”Default” />

</listeners>

</source>

</sources>

<switches>

<!– You can set the level at which tracing is to occur –>

<add name=”SourceSwitch” value=”Warning” />

<!– You can turn tracing off –>

<!–add name=”SourceSwitch” value=”Off” –>

</switches>

<sharedListeners>

<add name=”console”

type=”System.Diagnostics.ConsoleTraceListener”

initializeData=”false”/>

</sharedListeners>

<trace autoflush=”true” indentsize=”4″>

<listeners>

<add name=”console” />

</listeners>

</trace>

</system.diagnostics>

</configuration>

The TraceSource class is identified by the name of a source, typically the name of the application. The trace messages coming from a particular component can be initiated by a particular trace source, allowing all messages coming from that component to be easily identified. TraceSource defines tracing methods but does not actually provide any specific mechanism for generating and storing tracing data. The tracing data is produced by trace listeners, which are plug-ins that can be loaded by trace sources.

NOTE

  • You should not call the tracing methods during finalization. Doing so can result in an ObjectDisposedException being thrown.
  • You can customize the tracing output’s target by adding or removing TraceListener instances to or from the collection stored in the TraceSource.Listeners property. By default, trace output is produced using an instance of the DefaultTraceListener class.
  • Adding a trace listener to the Listeners collection can cause an exception to be thrown while tracing, if a resource used by the trace listener is not available. The conditions and the exception thrown depend on the trace listener and cannot be enumerated in this topic.

It may be useful to place calls to the TraceSource methods in try/catch blocks to detect and handle any exceptions from trace listeners.

The SourceSwitch class provides the means to dynamically control the tracing output. The preceding configuration file example shows how you can turn off tracing from a trace source and control the level at which tracing occurs. You can modify the value of the source switch without recompiling your application.  The trace listeners can optionally have an additional layer of filtering through a trace filter. If a trace listener has an associated filter, the listener calls the ShouldTrace method on that filter to determine whether or not to produce the trace information.

The trace listeners use the values of the Trace class properties Indent, IndentSize, and AutoFlush to format trace output. You can use configuration file attributes to set the Indent, IndentSize, and AutoFlush properties. The following example sets the AutoFlush property to false and the IndentSize property to 3.

EX.

<configuration>

<system.diagnostics>

<trace autoflush=”false” indentsize=”3″ />

</system.diagnostics>

</configuration>

EX.

The following code example shows the use of the TraceSource class to forward traces to listeners.

// The following configuration file can be used with this sample.

// When using a configuration file #define ConfigFile.

//<configuration>

//    <system.diagnostics>

//        <sources>

//            <source name=”TraceTest” switchName=”SourceSwitch” switchType=”System.Diagnostics.SourceSwitch” >

//                <listeners>

//                    <add name=”console” type=”System.Diagnostics.ConsoleTraceListener” initializeData=”false” />

//                    <remove name =”Default” />

//                </listeners>

//            </source>

//        </sources>

//        <switches>

//            <!– You can set the level at which tracing is to occur –>

//            <add name=”SourceSwitch” value=”Warning” />

//            <!– You can turn tracing off –>

//            <!–add name=”SourceSwitch” value=”Off” –>

//        </switches>

//        <trace autoflush=”true” indentsize=”4″></trace>

//    </system.diagnostics>

//</configuration>

#define TRACE

//#define ConfigFile

using System;

using System.Collections;

using System.Diagnostics;

using System.Reflection;

using System.IO;

using System.Security.Permissions;

namespace Testing

{

class TraceTest

{

// Initialize the trace source.

static TraceSource ts = new TraceSource(“TraceTest”);

[SwitchAttribute(“SourceSwitch”, typeof(SourceSwitch))]

static void Main()

{

try

{

// Initialize trace switches.

#if(!ConfigFile)

SourceSwitch sourceSwitch = new SourceSwitch(“SourceSwitch”, “Verbose”);

ts.Switch = sourceSwitch;

int idxConsole = ts.Listeners.Add(new System.Diagnostics.ConsoleTraceListener());

ts.Listeners[idxConsole].Name = “console”;

#endif

DisplayProperties(ts);

ts.Listeners[“console”].TraceOutputOptions |= TraceOptions.Callstack;

ts.TraceEvent(TraceEventType.Warning, 1);

ts.Listeners[“console”].TraceOutputOptions = TraceOptions.DateTime;

// Issue file not found message as a warning.

ts.TraceEvent(TraceEventType.Warning, 2, “File Test not found”);

// Issue file not found message as a verbose event using a formatted string.

ts.TraceEvent(TraceEventType.Verbose, 3, “File {0} not found.”, “test”);

// Issue file not found message as information.

ts.TraceInformation(“File {0} not found.”, “test”);

ts.Listeners[“console”].TraceOutputOptions |= TraceOptions.LogicalOperationStack;

// Issue file not found message as an error event.

ts.TraceEvent(TraceEventType.Error, 4, “File {0} not found.”, “test”);

// Test the filter on the ConsoleTraceListener.

ts.Listeners[“console”].Filter = new SourceFilter(“No match”);

ts.TraceData(TraceEventType.Error, 5,

“SourceFilter should reject this message for the console trace listener.”);

ts.Listeners[“console”].Filter = new SourceFilter(“TraceTest”);

ts.TraceData(TraceEventType.Error, 6,

“SourceFilter should let this message through on the console trace listener.”);

ts.Listeners[“console”].Filter = null;

// Use the TraceData method.

ts.TraceData(TraceEventType.Warning, 7, new object());

ts.TraceData(TraceEventType.Warning, 8, new object[] { “Message 1”, “Message 2” });

// Activity tests.

ts.TraceEvent(TraceEventType.Start, 9, “Will not appear until the switch is changed.”);

ts.Switch.Level = SourceLevels.ActivityTracing | SourceLevels.Critical;

ts.TraceEvent(TraceEventType.Suspend, 10, “Switch includes ActivityTracing, this should appear”);

ts.TraceEvent(TraceEventType.Critical, 11, “Switch includes Critical, this should appear”);

ts.Flush();

ts.Close();

Console.WriteLine(“Press any key to exit.”);

Console.Read();

}

catch (Exception e)

{

// Catch any unexpected exception.

Console.WriteLine(“Unexpected exception: ” + e.ToString());

Console.Read();

}

}

public static void DisplayProperties(TraceSource ts)

{

Console.WriteLine(“TraceSource name = ” + ts.Name);

Console.WriteLine(“TraceSource switch level = ” + ts.Switch.Level);

Console.WriteLine(“TraceSource switch = ” + ts.Switch.DisplayName);

SwitchAttribute[] switches = SwitchAttribute.GetAll(Assembly.GetExecutingAssembly());

for (int i = 0; i < switches.Length; i++)

{

Console.WriteLine(“Switch name = ” + switches[i].SwitchName);

Console.WriteLine(“Switch type = ” + switches[i].SwitchType);

}

#if(ConfigFile)

// Get the custom attributes for the TraceSource.

Console.WriteLine(“Number of custom trace source attributes = ”

+ ts.Attributes.Count);

foreach (DictionaryEntry de in ts.Attributes)

Console.WriteLine(“Custom trace source attribute = ”

+ de.Key + ”  ” + de.Value);

// Get the custom attributes for the trace source switch.

foreach (DictionaryEntry de in ts.Switch.Attributes)

Console.WriteLine(“Custom switch attribute = ”

+ de.Key + ”  ” + de.Value);

#endif

Console.WriteLine(“Number of listeners = ” + ts.Listeners.Count);

foreach (TraceListener traceListener in ts.Listeners)

{

Console.Write(“TraceListener: ” + traceListener.Name + “\t”);

// The following output can be used to update the configuration file.

Console.WriteLine(“AssemblyQualifiedName = ” +

(traceListener.GetType().AssemblyQualifiedName));

}

}

}

}

Tracing in ASP.Net

ASP.NET enables you to view diagnostic information about a request for an ASP.NET page. Tracing also enables you to write debug statements directly in your code without having to remove them from your application when it is deployed to production servers.

You can write variables or structures in a page, assert whether a condition is met, or simply trace through the execution path of your page or application. You can view tracing information appended to the end of a page, or in a separate trace viewer, or both.

Enabling Tracing

In order for tracing information to be gathered and displayed, you must enable tracing for the page or application. When you enable tracing, diagnostic information and custom tracing messages are appended to the output of the page and sent to the requesting browser.  Optionally, you can view this information from a separate trace viewer (Trace.axd) that displays trace information for every page in a given application. Tracing information can help you to clarify errors or undesired results as ASP.NET processes a page request.

Trace statements are processed and displayed only when tracing is enabled. You can control whether tracing is displayed to a page, to the trace viewer, or both.

ASP.NET tracing writes messages that are displayed on ASP.NET Web pages and the ASP.NET Trace viewer (Trace.axd). In contrast, the Trace class is used to trace write messages to the standard .NET Framework trace output (typically a console window).

To make it easier to track how your Web forms interact with business objects and other components, you can integrate ASP.NET tracing output with System.Diagnostics tracing to route all tracing messages to one of these outputs.

Common scenarios that use both ASP.NET tracing and Trace include Web pages that use middle tier business objects to interact with data and business rules, and pages that use enterprise services such as transactions and queues. In these situations the business and enterprise components play key parts in the successful execution of the page, and monitoring their execution flow across the multiple tiers of your application using a single tracing output is desirable.

Enable Tracing for an ASP.NET Page 

You can control whether tracing is enabled or disabled for individual pages. If tracing is enabled, when the page is requested, ASP.NET appends to the page a series of tables containing execution details about the page request. Tracing is disabled by default.

To enable tracing for a page:

1- Include an @ Page directive at the top of your .aspx file.

2- Add a Trace attribute and set its value to true, as shown in the following example:

<%@ Page Trace=”true” %>

NOTE

When tracing is enabled for a page, trace information is displayed in any browser requests that page. Tracing displays sensitive information, such as the values of server variables, and can therefore represent a security threat. Be sure to disable page tracing before porting your application to a production server. You can do this by setting the Trace attribute to false or by removing it.

You can also configure tracing in the Web.config file by setting the enabled, localOnly, and pageOutput attributes of the trace Element (ASP.NET Settings Schema). The Trace attribute in the @ Page directive takes precedence over attributes set in the trace element in the Web.config file. Therefore, even if you disable tracing in the Web.config file by setting the enabled attribute to false, the page might still show tracing information if the Trace attribute in its @ Page directive is set to true.

EX.

The following example show how to Configure the ASP.NET code tracing service that controls how trace results are gathered, stored, and displayed.

<configuration>

<system.web>

<trace

enabled=”false”

localOnly=”true”

mostRecent=”false”

pageOutput=”false”

requestLimit=”10″

traceMode=”SortByTime”

writeToDiagnosticsTrace=”false”

/>

<system.web>

</configuration>

Where

enable = Specifies whether tracing is enabled for an applciation.

Tracing must be eanbled in orer to sue the Trace.axd viewer. the default is false.

localOnly = Specifies whether the trace viewer (Trace.axd) is available only on the host

Web Server. The default is true.

mostRecent = Specifies whether the most recent application-level tracing output is

displayed and older trace data beyond the limits that are indicated by the

requestLimit is discarded. The default is false.

pageOutput = Specifies whether trace output is redndered at the end of each page. The

default is false.

requestLimit = Specifies the number of trace requests to store on the server. If the limit

is reached and the mostRecent attribute is false, trace is automatically

disabled. The maximum request limit is 10,000. If a value that is greater

than 10,000 is specified, it is silently rounded down to 10,000 by ASP.NET.

The default is 10.

traceMode = Specifies the order in which to display trace information. The traceMode

attribute an be one of the following possible values:

SortByCategory = Specifies that trace information is displayed in the order that tract

information is processed.

SortByTime = Specifies that trace information is displayed al

writeToDiagnnosticsTrace = Specifies whether ASP.NEt Trace message are forwarded to

the System.Diagnostics tracing infrastrcuture, for any

listeners that are registered to display Trace messages.

EX.

The following default element element is configured in the Machine.config file in the .NET Framework versions 1.0 and 1.1.

<configuration>

<system.web>

<trace

enabled=”false”

localOnly=”true”

pageOutput=”false”

requestLimit=”10″

traceMode=”SortByTime”

/>

<system.web>

</configuration>

EX.

The following code example demonstrates how to specify tracing configuration settings.

<configuration>

<system.web>

<trace enabled=”true”

pageOutput=”true”

requestLimit=”15″

mostRecent=”true” />

<system.web>

</configuration>

Application-Level ASP.Net Tracing

You can configure individual pages to display trace information. Alternatively, you can configure the application’s Web.config file so that all pages display trace information unless the page explicitly disables tracing. Setting application-level tracing is useful because you do not need to make changes to individual pages to enable and disable it.

You enable application-level tracing using the trace element in the Web.config file. When you enable application-level tracing, ASP.NET collects trace information for each request to the application, up to the maximum number of requests you specify.

The default number of requests is 10. By default, when the trace viewer reaches its request limit, the application stops storing trace requests. You can configure tracing to store either oldest tracing data (discarding newer items) or the most recent trace information (discarding older items).

As with page tracing generally, you can view trace information at the bottom of individual pages. Alternatively, you can use the trace viewer (Trace.axd) to view trace information collected and cached by ASP.NET when tracing is enabled.

If you want trace information to appear at the end of the page that it is associated with, you can set the trace element’s PageOutput attribute to true. If you enable application-level tracing, but you do not want trace information displayed for some pages, you can set the Trace attribute in those pages’ @ Page directive to false.

By default, application-level tracing can be viewed only on the local Web server computer. To make application-level trace information visible from remote computers, you can set the trace element’s LocalOnly attribute to false.

NOTE

To help keep your Web application secure, use the remote tracing capability only when you are developing or deploying your application. Be sure to disable it before you transfer your application to production Web servers by setting LocalOnly attribute to true in the Web.config file.

EX.

The following example shows an application trace configuration that collects trace information for up to 40 requests and allows browsers on computers other than the server to display the trace viewer.

<configuration>

<system.web>

<trace enabled=”true” requestLimit=”40″ localOnly=”false” />

</system.web>

</configuration>

Writing Custom ASP.Net Trace Messages

ASP.NET tracing enables you to append custom trace information to the end of an ASP.NET page or to the trace log. The trace information written to the trace log is viewable with the trace viewer. For more information, see How to: View ASP.NET Trace Information with the Trace Viewer. You can write trace information using the TraceContext class‘s Warn or Write methods. The difference between the two methods is that a message written with the Warn method appears in red text.

EX.

Web.Config

<configuration>

<system.web>

<trace enabled=”true”

pageOutput=”true”

requestLimit=”15″

mostRecent=”true” />

<system.web>

</configuration>

<%@ Page Language=”C#” Trace=”true”  %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd“>

<script runat=”server”>

void Page_Load(object sender, EventArgs e)

{

try {

if (IsPostBack)

{

switch (Request.Form[“__EVENTTARGET”])

{

case “WarnLink”:

throw new ArgumentException(“Trace warn.”);

break;

case “WriteLink”:

throw new InvalidOperationException(“Trace write.”);

break;

default:

throw new ArgumentException(“General exception.”);

break;

}

}

}

catch (ArgumentException ae) {

Trace.Warn(“Exception Handling”, “Warning: Page_Load.”, ae);

}

catch (InvalidOperationException ioe) {

Trace.Write(“Exception Handling”, “Exception: Page_Load.”, ioe);

}

}

</script>

<html xmlns=”http://www.w3.org/1999/xhtml” >

<head runat=”server”>

<title>Trace Example</title>

</head>

<body>

<form id=”form1″ runat=”server”>

<div>

<asp:LinkButton id=”WriteLink”

runat=”server”

text=”Generate Trace Write” />

<asp:LinkButton id=”WarnLink”

runat=”server”

text=”Generate Trace Warn” />

</div>

</form>

</body>

</html>

Enable Tracing for an ASP.Net Application

Instead of enabling tracing for individual pages, you can enable it for your entire application. In that case, every page in your application displays trace information.

Application tracing is useful when you are developing an application because you can easily enable it and disable it without editing individual pages. When your application is complete, you can turn off tracing for all pages at once.

When you enable tracing for an application, ASP.NET collects trace information for each request to the application, up to the maximum number of requests you specify. The default number of requests is 10. You can view trace information with the trace viewer.

By default, when the trace viewer reaches its request limit, the application stops storing trace requests. However, you can configure application-level tracing to always store the most recent tracing data, discarding the oldest data when the maximum number of requests is reached.

NOTE

  • To disable tracing for an individual page in the application, set the Trace attribute in that page’s @ Page directive to false. Any Write or Warn statements that you include in a page’s code are stored and returned to the trace viewer only.
  • If you want trace information to appear at the end of the page that it is associated with, set the trace element’s pageOutput attribute to true. If you want tracing information to be displayed only in the trace viewer, set the pageOutput attribute to false.

To enable tracing for an application

Open your Web site’s Web.config file. If no Web.config file exists, create a new file in the root folder and copy the following into it:

<?xml version=”1.0″?>

<configuration xmlns=”http://schemas.microsoft.com/.NetConfiguration/v2.0“>

<system.web>

</system.web>

</configuration>

EX.

The following example shows the application trace configuration collects trace information for up to 40 requests and allows browsers on computers other than the server of origin to display the trace viewer.

Trace information is not displayed in individual pages.

<configuration>

<system.web>

<trace enabled=”true” pageOutput=”false” requestLimit=”40″ localOnly=”false”/>

</system.web>

</configuration>

View ASP.Net Trace Information with the Trace Viewer

If you have enabled tracing for your application, when any page is requested, the page gathers trace information and executes any trace statements that it contains. You can view the trace output in the trace viewer.

The trace viewer enables you to choose a specific request from the pages that have been requested from your application.

If multiple requests have arrived for an application that has tracing enabled, the trace viewer lists the requests in the order in which they were processed. The information on the opening page of the trace viewer includes the time of the request, the file requested, the status code of the request, the HTTP verb associated with the request, and a View Details link that enables you to see more information about the request. The number of requests available will not exceed the requestLimit setting that you specified in the Web.config file.

To view trace details for a specific request

1- If the URL for your application is http://localhost/SampleApplication, navigate to http://localhost/SampleApplication/trace.axd to view the trace information for that application.

2- Select the View Details link for the request that you want to investigate.

3- To clear requests from the trace view, Select the clear current trace link to remove all the requests stored in the trace viewer.

NOTE

If the mostRecent attribute of the trace element is false, then the trace viewer tracks requests only up to the number of requests defined by the requestLimit attribute.

In that case, you cannot view requests made after the request limit is reached. Alternatively, you can set the mostRecent attribute to true so that the most recent tracing data is shown and older tracing data that exceeds the limit defined by the requestLimit attribute is discarded.

Reading ASP.Net Trace Information

You can view trace information appended at the end of an ASP.NET page or in the trace viewer. In both cases, the information displayed is the same. ASP.NET organizes

the trace information in a series of tables that provide diagnostic information about the request that you are viewing.

Trace Output Sections

1- Request Details

The Request Details section displays general information abou the current request and response.

Session ID= The session identification for the specified request.

Time of request = The time the request was made.

Request Encoding=  The character encoding for the request (for example Unicode (UTF-8)).

Request Type = The HTTP method used (GET or POST).

Status Code = The status-code value associated with the response.

Response Encoding = The character encoding for the response.

2-Trace Information

The Trace Information section displays the flow of page-level events. If you have created custom trace messages, the message are displayed in the Trace Information section.

The Trace Information includes the following columns:

Category = The custom trace category specified in a Warn or White method call, if any.

Message = The custom trace message specified in a Warn or Write methid if any.

From First(s) = The elapsed time in seconds since the first trace message was processed. The frst trace message appears at the tope of the list.

From Last(s) = The elapsed time is seconds between the procesing of the current trace message and the preceding trace message.

3- Control Tree

The Control Tree section displays information about ASP.Net server controls created in the page:

Control ID = The identification for the control. If you have not specfied an ID property for the control, ASP.NEt generates an ID

using the UniqueID property.

Type = The fully qualified type of the control.

Render Size bytes = The size in bytes of the rendered control (including child controls). THis is the size of the actual HTML, XML or

other format that is sent to the browser.

ViewState Size bytes = The size in bytes of the control’s viw state (Exculeding child controls).

ControlState Size bytes = The size in bytes of the control’s control state (exculding child controls).

4- Session State

The Session state section displays information about values stored in Session state, if any. This section will display the following information about each Session State:

Session Key = The Key for data stored in session state, if any.

Type = The fully qualified type of the object that stores the data.

Value = A string respresentation of the data stored in session state, if any.

5- Application State

The Applciation State secion display information about values stored in Application State if any. This section will display the following information about each Application State:

Application Key = The key for data stored in application state, if any.

Type = The fully qualified type of the object that stores the data.

Value = A string representation of the data stored in application state, if any.

6- Cookies Collection

==================

The Request Cookies and Response Cookies sections display informaiton about the cookies passed between the browser and the server on each request and response. The section displays both Persistent and Session cookies. ASP.Net creates some cookies automatically, such as those for cookie-based Session state and forms authentication. This collection displays the following information:

Name = The name of the cookie.

Value = The value of the cookie, or subkeys and values if the cookie is multivalued.

Size = The size in bytes of the cookie.

7-Headers Collection

The Headers Collection section displays information about request and response message header “name/value” pairs, which  provide information about the message body or requested resource. Header information is used to control how request

message are processed and response messages are created. This section displayes the following information:

Name = The name of the header.

Value = The value of the header.

8-Form Collection

The Form Collection section displays “name/value” pairs that show the form element values (control values)

submitted in a request during a POST (postback). This section displayes the following information:

Name = The name of the form variable.

Value = The value of the form variable.

9- Querying Collection

The Querystring Collection section shows the values passed in the URL. in a URL, query string information is separated

from the path information by a question mark( ?); mutiple query string elements are separated by an ampersand (&).

Query string “name/value” pairs are spearated by an equal sign (=). The QueryString property of the HttpRequest object returns

a NameValueCollection of query string variables. This section displayes the following information:

Name = The name of the query string variable.

Value = The value of the query string variable.

10- Server Collection

The Server Variables section displays a collection of server-related envrionment variables and request header information. The ServerVariables

property of the HttpRequest object returns a NameValueColleciton of server variables. This section displayes the following information:

Name = The name of the server variable.

Value = The value of the server variable.

Integrating ASP.Net Tracing with System.Diagnostics Tracing

You can use tracing to track the flow of execution for your application, to display data at critical points during a Web form’s life cycle, and to discover how the Web forms interact with various other components of your application.

Using tracing, you can examine HTTP request parameters that are submitted to your application, how much memory is being stored in view state for a particular Web form, and other useful profiling information.

The ASP.NET tracing mechanism writes messages that are displayed on ASP.NET Web pages and on the ASP.NET Trace viewer (Trace.axd), whereas the Trace class is used to write trace messages to the standard .NET Framework trace output (typically a console window).  To make it easier to track how the Web forms interact with business objects and other components, you can integrate ASP.NET tracing output with System.Diagnostics tracing to route all tracing messages to one of these outputs.

Common scenarios that use both ASP.NET tracing and the Trace class include Web pages that use middle-tier business objects to interact with data and business rules and pages that use enterprise services, such as transactions and queues.  In these situations, the business and enterprise components play key parts in the successful execution of the page and monitoring the execution flow of the pages across the multiple tiers of your application using a single tracing output is desirable.

The following example will do the following:

 

  • Creating a custom business component that can return data to a Web page. The component reads data from an XML file.
  • Creating a Web page that references the custom business object as a data source.
  • Enabling tracing for the Web page that is referencing the business object.
  • Writing trace messages to the Web page that is referencing the business object.
  • Writing Trace messages in a custom business object.
  • Configuring an ASP.NET application to write all trace messages to a single output.
  • Reading trace output.

EX.

1- Create a default.aspx, and add the following to the HTML Source:

<%@ Page Language=”C#” %>

<html>

<form runat=”server”>

<asp:objectdatasource

id=”AuthorsObjectDataSource”

runat=”server”

typename=”PubsClasses.AuthorClass”

selectmethod=”GetAuthors”/>

<asp:gridview

id=”GridView1″

runat=”server”

datasourceid=”AuthorsObjectDataSource” />

</form>

</html>

The Default.aspx page uses a business object named AuthorClass to interact with XML data.

2- Create the AuthorClass business Object under a directory named App_Code:

using System;

using System.Web;

using System.Data;

namespace PubsClasses

{

public class AuthorClass

{

private DataSet dsAuthors = new DataSet(“ds1”);

private String filePath =

HttpContext.Current.Server.MapPath(“~/App_Data/authors.xml”);

public AuthorClass()

{

dsAuthors.ReadXml (filePath, XmlReadMode.ReadSchema);

}

 

public DataSet GetAuthors ()

{

return dsAuthors;

}

}

}

 

3- The data file that AuthorClass uses is Authors.xml, and it will be located under a dirctory named App_Data:

<?xml version=”1.0″ standalone=”yes”?>

<dsPubs xmlns=”http://www.tempuri.org/dsPubs.xsd“>

<xs:schema id=”dsPubs” targetNamespace=”http://www.tempuri.org/dsPubs.xsd” xmlns:mstns=”http://www.tempuri.org/dsPubs.xsd” xmlns=”http://www.tempuri.org/dsPubs.xsd” xmlns:xs=”http://www.w3.org/2001/XMLSchema” xmlns:msdata=”urn:schemas-microsoft-com:xml-msdata” attributeFormDefault=”qualified” elementFormDefault=”qualified”>

<xs:element name=”dsPubs” msdata:IsDataSet=”true”>

<xs:complexType>

<xs:choice minOccurs=”0″ maxOccurs=”unbounded”>

<xs:element name=”authors”>

<xs:complexType>

<xs:sequence>

<xs:element name=”au_id” type=”xs:string” />

<xs:element name=”au_lname” type=”xs:string” />

<xs:element name=”au_fname” type=”xs:string” />

<xs:element name=”au_phone” type=”xs:string” />

</xs:sequence>

</xs:complexType>

</xs:element>

</xs:choice>

</xs:complexType>

<xs:unique name=”Constraint1″ msdata:PrimaryKey=”true”>

<xs:selector xpath=”.//mstns:authors” />

<xs:field xpath=”mstns:au_id” />

</xs:unique>

</xs:element>

</xs:schema>

<authors>

<au_id>172-32-1176</au_id>

<au_lname>White</au_lname>

<au_fname>Gerry</au_fname>

<au_phone>408 496-7223</au_phone>

</authors>

<authors>

<au_id>213-46-8915</au_id>

<au_lname>Green</au_lname>

<au_fname>Marjorie</au_fname>

<au_phone>415 986-7020</au_phone>

</authors>

</dsPubs>

4- To eable tracing and display ASP.Net trace messages the following is required:

a- Add a Trace attribute to the @Page directive, and then set Trace to true. The declaration enables

ASP.NEt tracing for the Web Page.

b-When you view the page in a Web Browser, you will see that the GridView

control is followed by tracing output.

5- To Write a Trace Messages, the following are required:

a- In the Default.aspx, enter the following code:

private void page_load(object sender, EventArgs e)

{

Trace.WriteLine(“ASP.NET TRACE”,”page_load called.”);

Trace.WriteLine(“ASP.NET TRACE”,”page_load finished.”);

}

b- Enable trace.axd, please create a <trace> tag within the configuration file located in the root directory of the current web application.

This <trace> tag should then have its “enabled” attribute set to “true”.

<configuration>

<system.web>

<trace enabled=”true”/>

</system.web>

</configuration>

NOTE

The trace messages are written to the ASP.Net trace output, and when the Default.aspx/Trace.axd is viewed, the trace messages will be displayed

in the Trace Information section between “Begin Load” and “End Load”. “Begin Load” and “End Load” are associated with Page_Load method.

6- Adding the trace messages to the AuthorClass business object:

a- The following code will be added to the following code into the AuthorClass Constructor:

System.Diagnostics.Trace.Write(“AuthorClass is created.”, “AUTHORCLASS TRACE”);

b- Add the following code into the AuthorClass.GetAuthors method:

System.Diagnostics.Trace.Write(“GetAuthors called.”,”AUTHORCLASS TRACE”);

NOTE

If you compile the business object that has the Trace compiler option, these trace messages are written to the system trace output. The trace messages are not written to the Default.aspx page, as the ASP.NEt trace messages are. To test this, view the Default.aspx page, and verify that only the same “ASP.Net Trace” messahes appear in the Tract Information table.

Routing all Tracing Output to the Web Form

1- To route Trace messages to an ASP.NET Web page, you must add a WebPageTraceListener object. You can add a trace listener either through configuration (recommended) or programmatically.

To add a WebPAgeTraceListener object the following has to be added to the Web.Config file:

<!– Web.Config Configuration File –>

<configuration>

<system.web>

<customErrors mode=”Off”/>

</system.web>

</configuration>

2- Add a WebPageTraceListener object to your application to route Trace messages to the ASP.Net tracing output. Place the following

code in your Web.Config file after the <system.web> section.

<system.diagnostics>

<trace>

<listeners>

<add name=”WebPageTraceListener”

type=”System.Web.WebPageTraceListener, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”/>

</listeners>

</trace>

</system.diagnostics>

The above configuration section adds a WebPageTraceListener object to the trace listeners collection for your applciation.

NOTE

Adding a WebPageTraceListener using the configuration file for your application is the recommended method of adding a trace listener. However, you can also add the trace listener programmatically, which is especially useful, if you are using complex tracing logic and ifferent types of trace listeners to trace your application, and the WebPageTraceListener is just one of manay. To add a trace listener to your application programmatically, create a Global.asax file and add the listener by adding the following code into the Application_Start method of your Global.asax file:

// Create a trace listener for Web forms.

WebPageTraceListener gbTraceListener = new WebPageTraceListener();

// Add the event log trace listener to the collection.

System.Diagnostics.Trace.Listeners.Add(gbTraceListener);

The above code will programmatically adds a WebPageTraceListener to the trace listeners collection for your application.

NOTE

  • With these steps, you have added a WebPageTraceListener to the trace listeners collection for the application.  Although ASP.NET displays trace messages whenever tracing is enabled for a page, System.Diagnostics trace messages are written only when the code in which the trace messages reside is compiled by using an explicit compiler switch—the TRACE switch. In other words, if you do not explicitly compile the AuthorClass using the TRACE switch, you will not see the trace messages, even with the WebPageTraceListener added.
  • You can configure your application to automatically compile using the TRACE switch, by adding the following section to your Web.config file after <System.diagnostics> section:

<system.codedom>

<compilers>

<compiler language=”c#;cs;csharp”

extension=”.cs”

compilerOptions=”/d:TRACE”

type=”Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089″ warningLevel=”1″ />

<compiler language=”VB”

extension=”.vb”

compilerOptions=”/d:Trace=true”

type=”Microsoft.VisualBasic.VBCodeProvider, System,    Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089″ />

</compilers>

</system.codedom>

NOTE

  • By default, this configuration section makes your application compile all modules with the TRACE option.
  • If you view the Default.aspx page now, you will see both ASP.Net and System.Diagnostics trace messages. If the ASP.Net and System.Diagnostics trace messages do not  appear, you might have to recompile the AuthorClass object.
  • From the trace information, you can see the AuthorClass object is created and its GetAuthors method is called during the PreRender method of the Web page life cycle. You can also see that there is a significant time lag when the AuthorClass object is created; the difference in time between the “Begin PreRender” message and the “AuthorClass is created.” message is significant. This is because the AuthorClass opens the Authors.xml file and initializes its DataSet during creation, which is a relatively costly operation.

Routing All Tracing Ouptut to .Net Framework Tracing

You might want to route ASP.NET tracing messages to the standard output for Trace messages, which can be a console window, disk, the Windows Event Log, or any other trace message output.

You can enable this message routing in the Web.config configuration file.

1- To route all ASP.NET trace messages to the system tracing output, add a new attribute, writeToDiagnosticsTrace, to the trace element under <system.web>, and then set writeToDiagnosticsTrace to true.

<system.web>

<trace writeToDiagnosticsTrace=”true”/>

<customErrors mode=”Off”/>

</system.web>

This configuration attribute instructs ASP.Net tracing to route ASP.Net trace messages to the standard system system tracing output mechanism.

To view the ASP.NET and System.Diagnostics trace messages in a context outside an ASP.NET page, use a TextWriterTraceListener object to write the trace messages to a file.

The TextWriterTraceListener object must be configured to write to a specific file. You can do this using the initializeData attribute of the <add> Element for <listeners> for <trace>.

2- Use the same steps that you followed to add the WebPageTraceListener object in the second procedure in “Routing All Tracing Output to the Web Form, to add a TextWriterTraceListener object to your Web.config file,

and configure the TextWriterTraceListener to write to a file in the application root directory named Asptesttrace.log, the following will be added to the <system.diagnostics> section of the Web.config file:

<system.diagnostics>

<trace autoflush=”true”>

<listeners>

<add name=”WebPageTraceListener”

type=”System.Web.WebPageTraceListener, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”/>

<add name=”TestTracer”

type=”System.Diagnostics.TextWriterTraceListener, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089″

initializeData=”<app root directory>\Asptesttrace.log” />

</listeners>

</trace>

</system.diagnostics>

NOTE

  • The initializeData attribute in the previous step has a placeholder value for the ASP.NET application root directory. If you try to a write trace messages to a file other than your application root directory, you might receive a security exception.  By default, ASP.NET does not allow writing files to locations on disk that are outside the application root directory, such as C:\. Additionally, you might have to grant Write permission to the trace log for the ASP.NET worker process account.
  • By default, you must wait to fill the trace buffer before trace data is written to the target stream.
  • To see trace data in the trace log immediately after requesting your ASP.NET page, flush the buffer with every trace write by setting the autoflush attribute set to true as you did in the preceding step.  The default value for the autoflush attribute is false.
  • To flush the buffer of trace information programmatically, call the Flush method.
  • For the business object that you developed, if you call the Flush method in the Page_Load method, and the autoflush attribute is false, the trace log will not show the trace data because the business object is rendered after the page Load event occurs.
  • You can add an EventLogTraceListener object to your applicationby doing one of the following steps:

1- To do this, you would add an EventLogTraceListener object either programmatically or by using the configuration file that uses the same procedure as for the WebPageTraceListener.

You can open the Event Log to review the trace messages that your application writes to the Event Log.

2- Change the business component to work with database data instead of with an XML file. You do not need to make any change to the controls on the page.

Conclusion

To debug a .NET Framework application, the compiler and runtime environment must be configured to enable a debugger to attach to the application and to produce both symbols and line maps, if possible, for the application and its corresponding Microsoft intermediate language (MSIL). After a managed application has been debugged, it can be profiled to boost performance. Profiling evaluates and describes the lines of source code that generate the most frequently executed code, and how much time it takes to execute them.

Tracing is an activity of recording the diagnostic information related to a specific web page that is being executed on the web server.

When the applications are in development stage, developers can use in-built debuggers for troubleshooting, but in the production environment, using debuggers becomes a huge task for administrators considering the security and related issues.

To debug Classic ASP applications, we were having no mechanism to track the execution flow of ASP pages. Thanks to .NET!!. Using .NET technology we can trace the flow with really less efforts. To collect the statistics like execution time, contents of certain object, “response.write” was the only way in classic ASP.

Using trace we are now able to view the HTTP headers, session state and likewise information on the trace output. Also, we have flexibility to add our own contents in the trace output.

 

References

 

Abilov, V (2002) Writing Custom .Net Trace Listeners [Online]. Available from: http://www.codeproject.com/Articles/2680/Writing-custom-NET-trace-listeners (Accessed: Oct. 23, 2013).

Microsoft Development Network (n.d.) Trace Listeners [Online]. Available from: http://msdn.microsoft.com/en-us/library/4y5y10s7.aspx (Accessed: Oct. 23, 2013).

Wasson, M. (2012) Tracing in ASP.Net Web API [Online]. Available from: http://www.asp.net/web-api/overview/testing-and-debugging/tracing-in-aspnet-web-api (Accessed: Oct. 23, 2013).

Microsoft Development Network (n.d.) Introduction to Instrumentation and Tracing [Online]. Available from: http://msdn.microsoft.com/en-us/library/x5952w0c.aspx (Accessed: Oct. 23, 2013).

Microsoft Development Network (n.d.) Trace Class [Online]. Available from: http://msdn.microsoft.com/en-us/library/system.diagnostics.trace.aspx (Accessed: Oct. 23, 2013).

Advertisements

2 Comments »

  1. Ita??s in fact a wonderful and valuable piece of info.Ia??m glad that you shared this helpful information with us.You should keep us informed like this.Many thanks for sharing
    maglia bayern monaco 2010 http://maglia-bayern-munich.greatbyeight.net

  2. 2
    testing Says:

    Heya i am for the first time here. I found this board and I in finding It really useful & it helped me out
    a lot. I am hoping to give one thing back and help others
    like you aided me.


RSS Feed for this entry

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: