Platforms, Frameworks & Libraries »
.NET Framework »
General
Intermediate
Getting the most out of Event ViewerBy Manoj GThis article talks about basics of event logging followed by the implementation details of how we can log messages effectively by using a custom log-file, event sources and event categories. Finally, it mentions the usefullness of troubleshooting links in error messages. |
VB.NET 1.0, Win2K, Windows, .NETVisual Studio, VS.NET2002, Dev
|
Advanced Search Sitemap |
|
|
Ideally, a good software application should never, or occasionally, come up with error conditions or exceptions. But as we all know, this is far from reality. So, when an exception does occur, a good application should just not log plain error messages, but also provide troubleshooting information and detailed information about the error in terms of its source and causes.
The Windows Event Viewer has always been the most suitable place to log error messages generated by applications. This article explains how we can use the .NET Event Logging API to effectively log error information. The article also touches upon some practices for effective error message management, like maintaining localized error messages and troubleshooting hyperlinks. We shall begin with some basics of event logging like event types, log-files, etc, and then cover the implementation aspects with respect to .NET.
There are basically five types of events that can be logged. Each event is of a particular type, and an error logging application indicates the type of event when it reports one. The Event Viewer uses this type, to determine the icon to display in the list view of the log.
Event Type |
Description |
Information | This indicates a significant, successful operation. For example, an event indicating that a service has started. |
Warning | Warning events indicate problems that are not immediately significant, but those that could cause problems in the future. Resource consumption is a good example for a warning event. |
Error |
Error events indicate significant problems that the user should know about. Error events usually indicate a loss of functionality or data. |
Failure Audit | Failure audit events are security events that occur when an audited access attempt fails. A failed attempt to open a file (due to lack of permissions) is an example for a failure audit event. |
Success Audit | Failure audit events are security events that occur when an audited access attempt fails. A failed attempt to open a file (due to lack of permissions) is an example for a failure audit event |
The following are the major elements that are used when logging events:
log-file is the place where the all event entries are made. The event logging service uses information stored in the EventLog
registry key. The EventLog
key (shown in Figure.1) contains several sub-keys called logfiles
.
log-file information in the registry is used to locate resources that
the event logging service needs when an application writes to and reads
from the event log. The default log-files are Application, Security, and System.
Figure 1: EventLog
key in the registry
Applications and services use the Application log-file, whereas device drivers use the System log-file. The system generates success and failure audit events in the Security log-file when auditing is turned on. Applications can also create custom log-files by adding an entry to the EventLog
registry key (This can be done programmatically as well). These logs
appear in the Event Viewer with the default log-files. It is a good
practice to have a separate log-file in the event viewer for your
application, as this makes isolating errors generated by your
application easier. Also, each log-file will be an independently
manageable unit. For instance, we can control the size of the log-file,
attach ACLs for security purposes etc.
Information about each event is stored in the event log in an event log record. The event log record includes time, type, source, and category information of each event.
The event source is the name of the software component (or a module of the application) that logs the event. It is often the name of the application, or the name of a subcomponent of the application, if the application is large. While applications and services should add their names to the Application log-file, or a custom log-file, the device drivers should add their names to the System log-file. The Security log-file is for system use only.
Figure 2: Registry Structure: Event Source
Each log-file contains sub-keys for event sources (as shown in Fig 2).Each event source contains information specific to the software that logs the events. The following table shows the various registry keys that can be configured for an event source:
Registry Value | Description |
CategoryCount |
Specifies the number of event categories supported. |
CategoryMessageFile |
Specifies the path for the category message file. A category message file contains language-dependent strings that describe the categories. |
DisplayNameFile |
Specifies the file that stores the localized name of the event log. The name stored in the specified file appears as the log name in the Event Viewer. If this entry does not appear in the registry for an event log, the Event Viewer displays the name of the registry sub key as the log name. |
DisplayNameID |
Specifies the message identification number of the log name string. This number indicates the message in which the localized display name appears. |
EventMessageFile |
Specifies the path for the event message file. You can specify multiple files, each separated by semicolons. An event message file contains language-dependent strings that describe the events. |
ParameterMessageFile |
Specifies the path for the parameter message file. A parameter message file contains language-independent strings that are to be inserted into the event description strings. |
TypesSupported |
Specifies a bit mask of supported types. |
Basically, event sources can be used to classify error messages as required by the application. For example, you can have sources like reporting, calculations, user interface, etc for an accounting application.
We shall see how we configure these values later in the article.
Categories help organize events so that we can filter them in the
Event Viewer. Each event source can define its own numbered categories,
and the text strings to which they are mapped. The categories must be
numbered consecutively, beginning with the number one. The total number
of categories is stored in the CategoryCount
key for the event source. Categories can be stored in a separate
message file, or in a file that contains messages of other types. We
shall talk more about creating categories under the section titled
Message Files.
Event identifiers identify a particular event uniquely. Each event source can define its own numbered events, and the description strings to which they are mapped. Event viewers present these descriptions strings to the user.
Message files are text files that contain information about the
various messages and categories that applications want to support.
These text files are then compiled as resource DLLs. Resource DLLs are
small and fast when compared to normal DLLs. The advantage of these
resource DLLs is that we can have messages written in multiple
languages. By using these DLLs, we can have a truly localized
application with localized error messages. Each event source should
register message files that contain description strings for each event
identifier, event category, and parameters. These files are registered
in the EventMessageFile
, CategoryMessageFile
, and ParameterMessageFile
registry values for the event source. We can create a single message
file that contains descriptions for the event identifiers, categories,
and parameters, or create three separate message files. Several
applications can share the same message file.
This article so far discussed the concepts behind event logging. Now, let us consider the implementation aspects with respect to .NET.
There are two ways to create an event log-file:
This can be done by adding an entry under HKEY_LOCAL_MACHINE\SYSTEM\Services\EventLog
.
To create log-files, event sources and also to log events in the event log we use the EventLog
class defined in the System.Diagnostics
namespace.
'Create the source, if it does not already exist.
If Not EventLog.SourceExists("MySource", "MyServer") Then
EventLog.CreateEventSource("MySource", "MyApp", "MyServer")
End If
In the code piece shown above, we are creating an event source called MySource
under MyApp log-file on the machine MyServer if one does not already exist.
Event sources can be created manually or programmatically (as shown earlier), similar to Event log-files. If you are creating sources manually, then you have to create several keys such as CategoryMessageFile
and EventMessageFile
under the source. The snapshot given below shows the registry entries after the log-file and event sources are created.
Figure 3: Event source registry entries
In Figure 3, we have created a log-file for the application called MyApp. Under this log-file, there are two sources MySource1 and MySource2. In the example shown above, Msg.dll in the temp directory is used to obtain both messages and category names (as provided for the CategoryMessageFile
and EventMessageFile
entries). The event source has three categories (CategoryCount
is set to 3), and all event types are supported (TypesSupported
is set to 7).
A detailed explanation of message text file syntax is beyond the scope of this document.
Given below is a sample message text file:
;//**************Category Definitions************
MessageId=1
Facility=Application
Severity=Success
SymbolicName=CAT1
Language=English
MyCategory1
.
MessageId=2
Facility=Application
Severity=Success
SymbolicName=CAT2
Language=English
MyCategory2
.
;//***********Event Definitions**************
MessageId=1000
Severity=Success
SymbolicName=MSG1
Language=English
My Error Message
.
MessageId=2000
Severity=Success
SymbolicName=GENERIC
Language=English
%1
.
Note: Message files can be in Unicode to support messages written in any language. In the example given above, messages are written in English. The categories and messages have also been provided in the same file.
We need to compile the message file to a resource-only DLL. The following steps explain the conversion process:
mc filename.mc.
rc -r -fo filename.res filename.rc
link -dll -noentry -out:filename.dll filename.res
To log an event into the event log, the WriteEntry
method of the EventLog
class can be used. Given below is a code snippet detailing how a message can be logged:
Dim objEventLog As New EventLog()
'Register the App as an Event Source
If Not objEventLog.SourceExists("MySource1") Then
objEventLog.CreateEventSource("MySource1","MyApp")
End If
objEventLog.Source = "MySource1"
objEventLog.WriteEntry("", EventLogEntryType.Error, 1000, CShort(1))
For the code sample above, refer to the message text file shown earlier.
Note a couple of things here. We are passing the EventID
parameter as 1000. This corresponds to the message "My Error Message"
in the message text file. This will be displayed as the message in the
event log. Also, we are passing the CategoryID
as 1. This corresponds to the category of MyCategory1.
Note that I am not passing any error message as this is picked up from
the message file. Figure 4 illustrates how the event log entry would
look like when the above code snippet is executed:
Figure 4: An event log entry with the EventID
and Category
We now have our own node in the event viewer. By looking at the event log, the user gets a fair amount of information like the source of the error and its category. Not only that, this makes filtering messages easier as we now have our own Sources and Categories. Also, by using the same method, we have effectively segregated error messages from the application code itself. This would help us maintain a uniform standard for error messages across applications, and also take us a step closer to localization.
Another good feature the Event Viewer provides is that of hyperlinks in the error messages, which can be linked to a web page detailing more about the error. This would help an end user understand and troubleshot the error. For example, the message given below has a link to a web page:
Figure 5: Troubleshooting Link given with an Error Message
On clicking this link, we would be prompted with a dialog box as shown below:
Figure 6: Posting Error Information to a designated place
When the user confirms to send this information, a web page can be
programmed to receive this information, and display troubleshooting
information to the user based on the EventID
, Category
, and Source
sent from the client (This information is sent as query string parameters).
The event viewer definitely provides a wealth of features through which error messages can be effectively logged and tracked. By exploiting these features, we would help end users to understand the errors and their sources better, and this in turn can simplify things for the support group.
Included with this article is a simple VB.NET project which just shows how the WriteEntry
method of the EventLog
class can be used. The zip also includes a .reg
file which should be run to create the custom log-file and to register
the event sources. Note that some paths are hard coded in the .reg file. So, change them accordingly. Finally, a batch file Compile.bat is included to compile the .mc file to create a message DLL.
General News Question Answer Joke Rant Admin
PermaLink |
Privacy |
Terms of Use
Last Updated: 17 May 2003 Editor: Smitha Vijayan |
Copyright 2003 by Manoj G Everything else Copyright © CodeProject, 1999-2009 Web13 | Advertise on the Code Project |