Skip Navigation LinksHome > View Post

Dogfooding Ukadc.Diagnostics

I've been making some more updates to the engine that powers this very blog (nothing you'll notice, all admin stuff) and it seemed prudent to move the logging system over to Ukadc.Diagnostics.

The new File listener

This particular codeplex project hasn't had a lot of love now, since last September, but I have a stack of updates I want to make, not least the FileTraceListener that was the most popular requested listener in our Survey. This has been completed now and it has some cool features, even if I do say so myself. I particularly like the way we use the Token system to create rolling files.

For example, you specify the filename on the filePath attribute of the listener

<sources>
    <source name="MySource" switchValue="All">
        <listeners>
            <add name="file"
                type="Ukadc.Diagnostics.Listeners.FileTraceListener, Ukadc.Diagnostics"
                output="{DateTime}: {EventType} - {Message}"
                filePath="{Year}-{Month}-{Day}.txt" />
        </listeners>
    </source>
</sources>

This file listener would now naturally roll over to a new file everyday and you can see that the file name would be of the format YYYY-MM-DD.txt (e.g. 2009-04-22.txt). Neat. You don't just have to use dates either. You could do it by the thread's principal name and process name!:

<add name="file"
     filePath="{PrincipalName}-{ProcessName}.txt"
     ... snipped for brevity ... />
    
Of course, the file doesn't have to roll - you can just specify a static name like "log.txt" etc.

Here are some of the Tokens supported by Ukadc.Diagnostics: {Message}, {Id}, {ThreadId}, {ProcessId}, {ProcessName}, {Callstack}, {DateTime}, {EventType}, {Source}, {ActivityId}, {RelatedActivityId}, {MachineName}, {Timestamp}, {PrincipalName}, {WindowsIdentity} and you can easily write your own by inheriting from PropertyReader as described here and here.

Back to dog food

We now use Ukadc.Diagnostics (replacing log4net) and I'm pretty happy with the setup. Here's the configuration:

<system.diagnostics>
    <sources>
        <source name="CommentPosted" switchValue="Information">
            <listeners>
                <add name="smtpComment" />
            </listeners>
        </source>
        <source name="Tjoc.Website.Blog.Dal" switchValue="Warning" >
            <listeners>
                <add name="smtpLog" />
            </listeners>
        </source>
        <source name="Tjoc.Website.Blog.Logic" switchValue="Warning" >
            <listeners>
                <add name="smtpLog" />
            </listeners>
        </source>
        <source name="Tjoc.Essentials" switchValue="Warning" >
            <listeners>
                <add name="smtpLog" />
            </listeners>
        </source>
        <source name="Tjoc.Website.UI" switchValue="Warning" >
            <listeners>
                <add name="smtpLog" />
            </listeners>
        </source>
    </sources>
    <sharedListeners>
        <add type="Ukadc.Diagnostics.Listeners.SmtpTraceListener, Ukadc.Diagnostics" name="smtpLog" initializeData="smtpLog" />
        <add type="Ukadc.Diagnostics.Listeners.SmtpTraceListener, Ukadc.Diagnostics" name="smtpComment" initializeData="smtpComment" />
    </sharedListeners>
</system.diagnostics>

As you can see we have five TraceSources in this system. One for each key assembly and an extra one for comments (yup, my comment notifications go through System.Diagnostics!).

Regrettably, because the built-in configuration capabilities of System.Diagnostics aren't great we had to create a seperate section that is referenced by the normal bits, for any complicated config. Above we reference two smtpTraceListeners called smtpLog and smtpComment. Below are the bits of configuration these are referencing.

<ukadc.diagnostics>
    <smtpTraceListeners>
    <!-- used to mail details of errors -->
        <smtpTraceListener name="smtpLog"
            host="snipped"
            port="25"
            username="snipped"
            password="snipped"
            from="snipped@snipped.com"
            to="snipped@snipped.com"
            subject="{EventType} - {MachineName} - {DateTime}"
            body="{MailToken}" />
        <!-- used to mail notifications of comment postings -->
        <smtpTraceListener name="smtpComment"
            host="snipped"
            port="25"
            username="snipped"
            password="snipped"
            from="snipped@snipped.com"
            to="snipped@snipped.com"
            subject="Comment Posted - TheJoyOfcode - {DateTime}"
            body="{MailToken}" />
    </smtpTraceListeners>
    <tokens>
        <!-- this token reused by both smtpTraceListeners above -->
        <token name="{MailToken}" format="{Message}
        =======
        Source={Source}
        Process={ProcessId},
        Thread={ThreadId},
        ActivityId={ActivityId},
        DateTime={DateTime},
        WindowsIdentity={WindowsIdentity},
        PrincipalName={PrincipalName}"
/>
    </tokens>
</ukadc.diagnostics>

Notice, that because the e-mail body created by both listeners is the same we create a new token (called '{MailToken}') and reference that from both the listeners.

Here's the code that uses the smtpComment (note that there is no direct dependency on Ukadc.Diagnostics here, just System.Diagnostics):

// at the top of the class
private static readonly TraceSource _commentNotificationSource = new TraceSource("CommentPosted");

// this inside the relevant method
if (_commentNotificationSource.Switch.ShouldLog(TraceEventType.Information))
{
    //don't want to build this string unless we have to
    string message = string.Format("Comment posted by: {0} \r\n\r\n {1} [mailto:{2}]\r\nPost: {3}", comment, name, email, url)
    _commentNotificationSource.TraceEvent(TraceEventType.Information, 0, message);
}

Another key trick we use on theJoyOfCode.com here is that the e-mail account we use for the smtpLog listener is a generic free on-line e-mail account. There's swathes of space up there and the account is heavily tooled with great search etc. A perfect home for that logging data! Not ideal for a production enterprise system but perfick for a lightly trafficked blog.

 
Josh Post By Josh Twist
4:51 AM
22 Apr 2009

» Next Post: Measuring the x,y distance between two elements in Silverlight
« Previous Post: Improving Performance of images used with 3D

Comments are closed for this post.

Posted by David Cuccia @ 12 May 2009 12:04 AM
Hi Josh,

FYI, I just ran across the "Common Logging Framework":

http://eeichinger.blogspot.com/2009/05/common-logging-20-for-net-released.html

© 2005 - 2014 Josh Twist - All Rights Reserved.