I’ve been looking at how to use the SPCriticalTraceCounter class for outputting messages in the Developer Dashboard. I came across a good post about how to do this by Frode Aarebrot, but it left me puzzled – what was the traceLevel integer about? Why wasn’t it an enumeration – like the Microsoft.SharePoint.Administration.TraceSeverity enum? Why those magic values? What happened if I used a wrong value?
Naturally, I started examining SPCriticalTraceCounter with Reflector.
Yes, this method is private, but it’s called by a public one that just passes in the current SPMonitoredScope..
First, our traceLevel integer is cast to a ULSTraceLevel. Looking at that enumeration:
Fine … but that doesn’t seem to match with the values that I’d read we should use in Frode’s post. He was taking about:
- 1 Critical
- 4 Exception (Watson)
- 6 Assert
- 8 Warning
- 10 Unexpected
- 15 Monitorable
Interesting … so the fact that the cast to the ULSTraceLevel didn’t find a matching enumeration value won’t cause an exception – that’s how C# behaves - but a check of Enum.IsDefined() might be nice.
Anyway, next, it appears that the TraceLevel must be less than 20 for anything to be traced. This is because there is a test of if the level is less than ULSTraceLevel.High (which is 20).
If it is, we end up calling the AddData method:
So, this sets up the data item to record. In here, it makes a call to TraceLevelString():
This casts our ULSTraceLevel back into an integer – and then tests the result in the switch statement. Yes, our input integer is cast twice just so it can be compared to 20.
Unfortunately, the values of the different cases in the switch don’t match the values in the ULSTraceLevel enumeration (above). <sarcasm>Oh, if only we could have used the enumeration for the switch statement directly. What, we could have?</sarcasm>
Or, even, what about using a public enumeration for the input traceLevel in the firstplace? Something like TraceSeverity, maybe? Oh, and if you’re curious, it’s values are:
So, basically, it’s the same as ULSTraceLevel – except that we’ve also got a ‘None’ value.
Conclusion? Well, Frode’s post is right – we’re stuck with using integer values that don’t match trace levels elsewhere. Let’s hope someone on the SharePoint Dev team stumbles across this gem for the next version. My other conclusion is that whoever wrote this in the first place was utterly clueless about how to use enumerations.