Skip Navigation LinksHome > View Post

System.Diagnostics hidden SourceLevels

I ran into a problem recently when working with the logging functionality built into .NET 2.0 inside the System.Diagnostics namespace. Everything's mostly very simple in here.

System.Diagnostics.Trace.TraceInformation("Something happened");
System.Diagnostics.Trace.TraceError("Oh no! Something happened");

As you can see, we've logged two messages one at an Information level and another at Error level. You may remember that I've discussed logging levels before.

If you're using System.Diagnostics seriously, you're probably using a TraceSource instance, which lets you do similar things to the above and you can specify the level from the TraceEventType enumeration.

TraceSource mySource = new TraceSource("mySource");
mySource.TraceInformation("Something happened");
mySource.TraceEvent(TraceEventType.Error, 0, "Oh no! Something happened");

Now that you have access to the TraceEventType enumeration you may notice that there are quite a few values here:

public enum TraceEventType
{
    Critical = 1,
    Error = 2,
    Warning = 4,
    Information = 8,
    Verbose = 16,
    Start = 256,
    Stop = 512,
    Suspend = 1024,
    Resume = 2048,
    Transfer = 4096,
}

Controlling the level

Similar to the main subject of the previous post I mentioned, you can control the output of the logging in System.Diagnostics by modifying a 'switch' against the TraceEventType of each event.

The configuration looks like this...

<configuration>
    <system.diagnostics>
        <sources>
            <source name="mySource" switchName="SourceSwitch">
                <listeners>
                    <add name="myListener"
                        type="System.Diagnostics.XmlWriterTraceListener"
                        initializeData= "Test.log" />
                </listeners>
            </source>
        </sources>
        <switches>
            <!-- this is the part we're interested in -->
            <add name="SourceSwitch" value="Warning" />
        </switches>
    </system.diagnostics>
</configuration>

Here, we configure a Source and wire it up to the XmlWriterTraceListener (which will dump logging events into a test.log file nicely marked up in Xml). We also point our Source at a switch with a value of Warning. This means that we will only 'dump' events of TraceEventType.Warning or above. Easy peasy.

MSDN has an article on the various settings you can use in the switch value. In summary, it shows these:

  • Off (0)
  • Error (1)
  • Warning (2)
  • Info (3)
  • Verbose (4)
... which map exactly to the TraceLevel enumeration. You can even use the numbers instead of the stringified enum value.

Having said that, when using a TraceSource you'll find little correlation between the TraceEventType and the TraceLevel. In fact, I couldn't get any of these to write out Start, Stop, Suspend, Resume or Transfer level events.

This had me baffled for sometime but some digging in reflector shows that this is because TraceSource actually uses a SourceSwitch, not a TraceSwitch.

The SourceSwitch uses a totally different enum called SourceLevels:

public enum SourceLevels
{
    All = -1,
    Off = 0,
    Critical = 1,
    Error = 3,
    Warning = 7,
    Information = 15,
    Verbose = 31,
    ActivityTracing = 65280,
}

Fortunately, we can use these values (stringified or numeric) in our switches... exactly what's going to happen might not be clear so I've created the following grid to help you out. The Items down the left are the SourceLevels you specify in the config. And the items across the top represent the TraceEventType values tied to a particular event. A tick indicates that this level event will log against this SourceLevel.

SourceLevels against TraceEventType

Next, we'll be looking at how I generated this chart using only Xaml (via WPF) and a simple MultiValueBinding!

See you then.

 
Josh Post By Josh Twist
11:49 AM
02 Jul 2007

» Next Post: Sortable ListView in WPF
« Previous Post: Compiled and checked in

Comments are closed for this post.

Posted by Jason Michenert @ 16 Sep 2008 1:47 PM
You sir, are the man. This has been bothering me for awhile. Everything I have read indicates that you can combine the source levels using bitwise operations, but I couldn't get the list of what those trace levels were. (I was trying to filter out the verbose messages from log files.) That's because, as you pointed out, they are really source levels. Thanks a ton for your excellent post !!

Posted by dg @ 06 Oct 2008 5:01 AM
Thanks for the post - one minor comment: The ActivityTracing bits are the high order bits (decimal 65280 is 1111111100000000 binary) so the columns should be flipped around.

© 2005 - 2014 Josh Twist - All Rights Reserved.