Macaw TraceInfo WebPart, or how to view Trace output in a page using only a WebPart
Introducing the Macaw TraceInfo WebPart
What a pain it is to see your WebPart fail on a SharePoint production server where you cannot simply start Visual Studio and debug the failing code... In many cases, you don't even have (physical) access to the server. If you used Trace statements in your WebPart, then you can configure trace listeners in SharePoint's web.config and have the Trace output sent to the event log or file.
But life can be simpler than that: I am presenting a FREE SharePoint WebPart with full source code here that shows all the Tracing output in code that is executed during the Page Request without any configuration. It's a great way to view System.Diagnostics tracing output at will without even having production server access to event log or log files... Just drag the Macaw TraceInfo WebPart onto the page and your Tracing output will show up! Well, ok, if you used System.Diagnostics.Trace.Write() or System.Diagnostics.Trace.WriteLine() statements in your code... This code can be even business logic code; as long it contains System.Diagnostics.Trace statements, its output can be viewed by the TraceInfo WebPart.
Feature Summary
- Automagically collects System.Diagnostics.Trace output without web.config editing, just drag the WebPart on a page and it shows the Trace information.
- Shows all System.Diagnostics.Trace output from all code that runs during the request of the page.
- Filtering Trace output by Trace Category name by entering a filter value on the TraceInfo toolpart.
- WebPart is hidden from non-SiteAdministrative users by default, but can be made visible to any user by de-selecting a checkbox on the TraceInfo toolpart.
In the screenshot below the "Processen per Categorie" is a custom developed web part which uses Trace statements in the code. The TraceInfo web part below it has been dragged onto the page and automagically starts showing every Trace output during the page request. (The web part by the way reads a document library with InfoPath documents and groups these documents on specified columns of the document library.)

Technique
The basic technique is a custom TraceListener, WebPartTraceInfoListener, which collects all System.Diagnostics. tracing output and stores it an ArrayList on the Request.Items collection for later processing. The Request.Items collection exists during the whole Page Request lifespan and can be accessed by all HttpModules, the HttpHandler and any components like WebParts.
public class WebPartTraceInfoListener:TraceListener
{
public override void Write(object o)
{
CacheTraceText(o.ToString(), String.Empty, false);
}
...
private void CacheTraceText(string message, string category, bool newLine)
{
if (HttpContext.Current != null)
{
// Test if the ArrayList is alread on the Items collection
ArrayList traceTexts = HttpContext.Current.Items[Const.TraceInfoContextKey] as ArrayList;
// If not, create it.
if (traceTexts == null)
{
traceTexts = new ArrayList();
HttpContext.Current.Items[Const.TraceInfoContextKey] = traceTexts;
}
// Add the trace info to the ArrayList.
traceTexts.Add(new TraceInfo(message, category, newLine));
}
}
}
The TraceInfo struct is a helper struct which stores a System.Diagnostics.Trace message, category and current DateTime and whether Write or WriteLine was used.
Showing the collected Trace output is as simple as collecting it, because the only thing the WebPart needs to do is accessing the ArrayList with Trace outputs on the Request.Items collection and render them in sequence. I chose for a table output with three columns with time of the Trace output, Trace Category and message text. You can find details in the source code.
The Macaw TraceInfo WebPart injects a custom TraceListener (WebPartTraceInfoListener) into System.Diagnostics TraceListeners collection at initialization of the WebPart:
public class TraceInfoWebPart : Microsoft.SharePoint.WebPartPages.WebPart
{
private static WebPartTraceInfoListener _traceInfoListener = null;
private WebPartTraceInfoListener TraceInfoListener
{
get
{
if (_traceInfoListener == null)
{
_traceInfoListener = new WebPartTraceInfoListener();
}
return _traceInfoListener;
}
}
protected override void OnInit(EventArgs e)
{
if (!OnlyVisibleToAdmin || UserIsAdmin)
{
// Add the TraceInfoListener to the Diagnostic Listener collection
// if not already part of the collection.
if (!System.Diagnostics.Trace.Listeners.Contains(TraceInfoListener))
{
System.Diagnostics.Trace.Listeners.Add(TraceInfoListener);
}
}
base.OnInit (e);
}
....
}
And this is all to it!
The ZIP file contains the WebPart package, ready to be deployed to the GAC of your SharePoint server (either Portal or WSS-only) and the C# source code of the solution. The Package actually contains two WebParts: the Macaw TraceInfo WebPart and a dummy WebPart which issues two Trace statements to test the TraceInfo WebPart.
Download the Macaw TraceInfo WebPart binary and source code
UPDATE Sep 7, 2006: Macaw Internal Support is pretty overactive cleaning the download directory each time, so I've changed the download location to where they can't touch the file ;-)
Tip: Place the TraceInfo WebPart as low as possible on the WebPart page.
Note: Of course you can use the Enterprise Instrumentation Framework block or LOG4NET, but this is in many cases too 'large' implementation for a few simple webparts. Trace statements are simple and consume just very little performance when no listeners are attached.