I frequently receive calls asking why an application is not behaving as expected. Many times, a quick look at the database can provide the answer. Sometimes, however, things are a little more involved. Our internal applications make extensive use of event logs. The event logs will contain error messages, warnings, and in the case of some occasionally connected systems a log of all the data received. Trying to manually forge through the event logs can be a daunting task. The answer, of course, is to let a computer do most of the searching for you. Here is a class with a couple static methods that you can use to quickly limit the number of event log entries that you have to manually search through:
public enum EventLogFilterType { TimeGenerated, UserName, MachineName, Category, Source, EntryType, Message, EventID } public sealed class SearchEventLog { // Prevent this class from being instantiated. private SearchEventLog() {} public static EventLogEntry[] FilterEventLog(EventLogFilterType FilterType, IEnumerable Entries, object Criteria1, object Criteria2) { ArrayList FilteredEntries = new ArrayList(); foreach (EventLogEntry Entry in Entries) { switch (FilterType) { case EventLogFilterType.TimeGenerated: if (Entry.TimeGenerated >= (DateTime)Criteria1 && Entry.TimeGenerated <= (DateTime)Criteria2) FilteredEntries.Add(Entry); break; } } EventLogEntry[] EntriesArray = new EventLogEntry[FilteredEntries.Count]; FilteredEntries.CopyTo(EntriesArray); return (EntriesArray); } public static EventLogEntry[] FilterEventLog(EventLogFilterType FilterType, IEnumerable Entries, object Criteria) { ArrayList FilteredEntries = new ArrayList(); foreach (EventLogEntry Entry in Entries) { switch (FilterType) { case EventLogFilterType.Category: if (Entry.Category == (string)Criteria) FilteredEntries.Add(Entry); break; case EventLogFilterType.EntryType: if (Entry.EntryType == (EventLogEntryType)Criteria) FilteredEntries.Add(Entry); break; case EventLogFilterType.EventID: if (Entry.EventID == (int)Criteria) FilteredEntries.Add(Entry); break; case EventLogFilterType.MachineName: if (Entry.MachineName == (string)Criteria) FilteredEntries.Add(Entry); break; case EventLogFilterType.Message: if (Entry.Message == (string)Criteria) FilteredEntries.Add(Entry); break; case EventLogFilterType.Source: if (Entry.Source == (string)Criteria) FilteredEntries.Add(Entry); break; case EventLogFilterType.UserName: if (Entry.UserName == (string)Criteria) FilteredEntries.Add(Entry); break; } } EventLogEntry[] EntriesArray = new EventLogEntry[FilteredEntries.Count]; FilteredEntries.CopyTo(EntriesArray); return (EntriesArray); } }
First, an enumeration is defined for the list of possible fields that can be used to filter the event log entries. Next, the SearchEventLog class is listed; it includes two methods for filtering. The first FilterEventLog() method is used to filter event log entries that fall between the two criteria conditions. This method is currently only used to limit the event log entries to a date range. The second FilterEventLog() method is used to filter event log entries that exactly match the criteria condition.
You now can filter any event log with a few simple lines of code. The code below retrieves all the entries in the “System” event log and then applies two filters to the results. Finally, the filtered entries are displayed on the console.
EventLog Log = new EventLog("System"); EventLogEntry[] Entries = SearchEventLog.FilterEventLog(EventLogFilterType.TimeGenerated, Log.Entries, DateTime.Parse("1/1/2009"), DateTime.Parse("1/31/2009")); Entries = SearchEventLog.FilterEventLog(EventLogFilterType.EntryType, Entries, EventLogEntryType.Error); foreach (EventLogEntry Entry in Entries) { Console.WriteLine(" Message: " + Entry.Message); Console.WriteLine(" Category: " + Entry.Category); Console.WriteLine(" EntryType: " + Entry.EntryType.ToString()); Console.WriteLine(" Source: " + Entry.Source); }
Here is a sample of the output from the above example when run on my computer:
Message: The time provider NtpClient is configured to acquire time from one or more time sources, however none of the sources are currently accessible. No attempt to contact a source will be made for 14 minutes. NtpClient has no source of accurate time. Category: (0) EntryType: Error Source: W32Time Message: DCOM was unable to communicate with the computer TRSBETASQL using any of the configured protocols. Category: (0) EntryType: Error Source: DCOM
By combining several filters, you can extract exactly the entries you are interested in from any event log. I have saved a huge amount of time by using this method to monitor the event logs on our test and production servers for potential problems.
About the Author
Jay Miller is a Software Engineer with Electronic Tracking Systems, a company dedicated to robbery prevention, apprehension, and recovery based in Carrollton, Texas. Jay has been working with .NET since the release of the first beta and is co-author of Learn Microsoft Visual Basic.Net In a Weekend. Jay can be reached via email at jmiller@sm-ets.com.