The System.Diagnostics namespace provides a simple and extensible model for tracing. This post is about leveraging that model in ASP.NET (Web Applications, ASMX Web Services, Http Modules and Http Handlers).
Problem
The System.Diagnostics classes, Trace and Debug, simplify instrumentation by placing it's configuration outside your code, in one centralized place. That place can be an initialization method or a configuration file. Use of a configuration file allows you to change instrumentation behavior after deployment.
Moreover, the TraceListener model implemented by these classes allows you to extend instrumentation behavior by injecting your own custom listeners into the instrumentation infrastructure. Though you do have to implement custom listeners in code, you still have the choice of injecting them in initialization code or using a configuration file.
ASP.NET has an additional model for instrumentation. The key to this model is the System.Web.TraceContext class, which is widely documented, in particularly on MSDN.
The TraceContext class traces ASP.NET activity in detail and is controlled by the trace element in <system.web> in your configuration file.
You can add your own traces to its output using its Warn and Write methods. But with this model, you have limited control over where traces go and at first glance it doesn’t allow you to extend the model with your own custom listeners.
But, actually, it does. In fact you have two options:
- Use System.Diagnostics.Trace as you would in a Windows client application.
- Use System.Web.TraceContext with System.Diagnostics.Trace
Solution 1: Use System.Diagnostics
Add the system.diagnostics element in the Web.config for your ASP.NET application. Here is what I use to send my traces to a file called Traces.txt. In this case, I am using a built-in listener class, but you can replace it with a custom listener in exactly the same way as you would in a Windows client application.
<system.diagnostics>
<trace autoflush="true">
<listeners>
<clear/>
<add name="TraceToFile"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="Traces.txt"/>
</listeners>
</trace>
</system.diagnostics>
In your code, you can now make calls to:
System.Diagnostics.Trace.Write("");
and your traces will go to the Traces.txt file.
This works regardless of how you configured TraceContext through the <system.web> configuration element.
Oh, one other thing.
For this to work, just like in a Windows client application you have to enable the TRACE compiler option. In ASP.NET applications you do this in the configuration file through the compileOptions attribute of the compiler element:
Here is the relevant snippet from my web.config:
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" warningLevel="4"
type="Microsoft.CSharp.CSharpCodeProvider,
System,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"
compilerOptions="/d:TRACE">
<providerOption name="CompilerVersion" value="v3.5"/>
. . .
</compiler>
</compilers>
</system.codedom>
Solution 2: Use System.Web.TraceContext with System.Diagnostics
The first solution allows you to control your own traces – but doesnt give you any of the trace information from ASP.NET. Tracing of that information is still controlled by the trace element in <system.web>, and, if, enabled will go wherever TraceContext information goes.
This solution allows you to direct ASP.NET traces from TraceContext to the System.Diagnostics.Trace infrastructure. This way, your configuration in the system.diagnostics will handle your traces and those from ASP.NET.
For this option, implement Option 1 and, in addition, add the following in <system.web>
<system.web>
. . .
<trace enabled="true" writeToDiagnosticsTrace="true"/>
. . .
</system.web>
Now, in your code, don’t use:
System.Diagnostics.Trace.Write("");
Use one of these instead:
Context.Trace.Write(""); // for an asmx WebService
Page.Trace.Write(""); // for an aspx Page
HttpContext.Current.Trace.Write(""); // for an IHttpHandler or IHttpModule
If you use the configuration file snippets from this post, you will get all instrumentation information from ASP.NET and your own instrumentation calls directed to a file called Traces.txt.
You are back in control again : )