views:

21

answers:

1

I have a TraceSource object that I use to log the initialization of a VB.Net application. It has several TraceListeners attached:

  • ConsoleTraceListener
  • TextWriterTraceListener
  • EventLogTraceListener

For the first two I want the entry output to be "raw" - that is, without the standard header:

SourceName TraceEventType: Id :

I have implemented a wrapper that does this when the TraceEventType is set to Verbose:

If _buffer.EventType = TraceEventType.Verbose Then
    For Each listener As TraceListener In _traceSource.Listeners
        listener.Write(_buffer.Text)
    Next
Else
    _traceSource.TraceEvent(_buffer.EventType, id, _buffer.Text)
End If

I could do this for all the tracing, but then all entries in the EventLog would be listed with Level = Information. So I want to be able to specify the severity of the trace message, but I can't find any method on the TraceSource or the TraceListeners that allows me to do this. As far as I can tell, TraceListener has these options for writing to it:

  • Write()
  • WriteLine()
  • TraceData()
  • TraceEvent()
  • TraceTransfer()

The last 3 allows for providing a TraceEventType (which correctly labels the EventLog entries, but the resulting output to the console and the log file then includes the prefixes and ends up like this (for example):

Bootstrapper Warning: 0 : Failed to validate assembly

Is there a way to override how the ConsoleTraceListener and TextWriterTraceListener format their output to not include this header, while at the same time being able to tag the entries with a TraceEventType (for the EventLog)?

This is the best I have come up with so far:

For Each listener As TraceListener In _traceSource.Listeners
    If listener.GetType Is GetType(ConsoleTraceListener) OrElse listener.GetType Is GetType(TextWriterTraceListener) Then
        listener.Write(_buffer.Text)
    Else
        listener.TraceEvent(Nothing, _traceSource.Name, _buffer.EventType, id, _buffer.Text)
    End If
Next

This seems to work, but in the documentation on the TraceListener.TraceEvent Method from Microsoft, it says:

Important: This method is not intended to be called directly by application code but by members of the Debug, Trace, and TraceSource classes to write trace data to output.

..so I'm not sure if it's a good thing to do?

Edit:

I just realized that if I do something like my last example here, I don't need the TraceSource at all, since it's being bypassed anyway. But it also means I have to implement my own filtering and switching mechanisms (but that is maybe an OK price to pay to get it to work the way I want).

A: 

Look at the Ukadc.Diagnostics project on codeplex. It is an addon to System.Diagnostics that gives you the ability to format your logging/tracing output however you would like (similar to what you can do with log4net and NLog). You use it through configuration, so your code will not take a direct dependency on the library. The library comes with configurable objects for formatting and the custom TraceListeners required to take advantage of the formatting. The library also makes it easy for you to write your own formatting "tokens" and your own TraceListener.

For example, you could configure the Ukadc.Diagnostics ConsoleTraceListener to use a formatting statement something like this:

{DateTime} {Source} {EventType} {Message}

Every message logged would cause the date/time, the source name, the event type, and the message.

Try it out, I think that you will like it. I have used it some myself (mostly for prototyping, not for a "real" product yet) and have had good success.

Note that for some tokens (like DateTime), you can also apply standard formats that are appropriate for the type (e.g. for DateTime you can specify the format in which the date/time should be written).

The file trace listener that comes with Ukadc.Diagnostics also allows its filename to be specified using the token system.

wageoghe
Thanks, I'll have a look (though I prefer not to use external addons, for some reason). And now I have also made my own tracing system where I can do similar things. My class functions similarly to TraceSource, but it has two listener collections. One that functions in the standard way, using TraceEvent(), and the other uses the "raw" Write() function. Every logged message is pushed to all listeners in both categories (depending on certain flags etc), so you can add the listeners that require EventType tagging in one, and the ones with plain/custom formatting in the other. Works well.
d7samurai
I think the library is really cool, so go ahead and try it out, you might like it. One way it could help your workflow is that you could use the same set of TraceListener classes, but change what actually gets written via configuration. So, you could have a "raw" format associated with some listeners (Console and TextWriter) and an "event" format associated with others (EventLog). If you decide next week or next month that you want to add or remove some information from either format, then you just have to change the format in the app.config. No code changes. Good luck!
wageoghe