The EventLogTraceListener and EventLogEntryType

If you've ever used the EventLog class, you know it's a convenient way to write entries into any of the event logs on a machine. The WriteEntry method has a number of overloads and one of them allows you to specify an EventLogEntryType member to indicate the type of event log entry to create -- Information, Warning, Error, SuccessAudit or FailureAudit.

Now suppose you're using the EventLogTraceListener class to write trace messages out to the event log. You may notice that all of your trace messages go in as EventLogEntryType.Information. Now suppose you want to change that to Warning? There is no such property on the EventLogTraceListener to set the EventLogEntryType. And you can verify that it's a lost cause by pulling out Reflector and looking at the EventLogTraceListener's Write method:

public override void Write(string message)
{
      if (this.eventLog != null)
      {
            this.eventLog.WriteEntry(message);
      }
}

That particular overload always writes an event log entry as type "Information". But we can easily remedy this with our own TraceListener class.

First, I created a very simple TraceListener that writes to the Application EventLog. It accepts a string parameter in the constructor which defines the EventLogEntryType member to use when writing entries into the event log. The string comes from the "initializeData" parameter of the <add> element in our app.config file. The class exists in an assembly called "CustomListener".

using System;
using System.Diagnostics;
using System.Reflection;

namespace CustomListener
{

	public class PSListener : TraceListener
	{
		private EventLog _eventLog;
		private EventLogEntryType _logType;

		public PSListener(string logType) : base()
		{
			_eventLog = new EventLog("Application");
			_eventLog.Source = Assembly.GetEntryAssembly().GetName().Name;
			_logType = (EventLogEntryType) Enum.Parse(typeof(EventLogEntryType), logType);
		}

		public override void Write(string message)
		{
			_eventLog.WriteEntry(message, _logType);
		}

		public override void WriteLine(string message)
		{
			Write(message + Environment.NewLine);
		}

	}
}

I created a really simple test application:

using System;
using System.Diagnostics;

namespace SampleApp
{
	class Class1
	{
		[STAThread]
		static void Main(string[] args)
		{
			Trace.WriteLine("App Starting");

			Trace.WriteLine("App Ending");
		}
	}
}

Then I added my trace listeners to the TraceListeners collection via an app.config file (note that I added a regular EventLogTraceListener as well as my custom one). This is where I use the "initializeData" parameter to define the type of EventLogEntryType I want the TraceListener to use:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<system.diagnostics>
		<trace autoflush="true" indentsize="4">
			<listeners>
				<add name="myListener" type="System.Diagnostics.EventLogTraceListener" initializeData="mySource" />
				<add name="customListener" type="CustomListener.PSListener,CustomListener" initializeData="Warning" />
			</listeners>
		</trace>
	</system.diagnostics>
</configuration>

Finally, make sure the CustomListener DLL exists in the same directory as your sample app. After running, check your Application event log. You should have four new entries. Two from the default EventLogTraceListener with a source of "mySource" (Type = Information) and two from the custom trace listener with a source of "SampleApp" and a Type of Warning.

2 Comments

  • I can understand why the default EventLogTraceListener defaults to Information entries - tracing is about leaving a trail of information to find your way. However, as usual, it is annoying to discover that too many classes in the framework have overly restrictive access modifiers. There should be more protected virtual methods and less private or internal methods. Too often I have to do as you have done and build a whole new class just to add slightly more functionality to the framework.

  • Kevin,

    I just tried it in IE6 and it chops off the code also. However, you can select it with the mouse and copy it to the clipboard. That'll grab all the text even though IE isn't displaying it.

Comments have been disabled for this content.