Event Logging and Distributed Logging in ASP.NET (2/6)
Event Logging in .NET
Limitations of the .NET Logging API
Now that we have taken a look at what can be done let us see what cannot be done.
When an event log is written using the standard Win32 API calls, the system stores a structure that contains, among other things, an integer, called the message identifier. It also stores any replacement strings--called inserts for the message--instead of storing the message text itself. There are three main advantages in doing things this way. First, the message store now is significantly smaller, also making logging operations faster. Second, just storing the message ID and replacement strings also means that the same message can be viewed in different languages if required. All that is required is the lookup table of the messages in the particular language desired. Finally, different sections of programs (or different programs altogether) logging the same event now do not have to worry whether they are sending the correct textual string for the message. In the next section when we develop our event logging library we will remedy this situation by allowing events to have a message id along with inserts. (It is intriguing that while the .NET API allows the reading of message ids and inserts from the built-in Windows event logs, it does not allow writing such entries.)
Another problem that is usually faced with event logging is in distributed applications like a Web farm scenario. In this case the disparate parts of an application are on different machines. If each application logs to its local event log then seeing the chronology of events would entail putting together event logs from all the machines. This could be a very cumbersome task. A better solution would be for all machines to write events to the event log of a central machine. This however has the following shortcomings:
- If we want to change the central event store to some other computer then we have to change the configurations on all machines that are logging. Not a pleasant scenario for application management.
- Since the central event log is now logging events from many sources it can quickly grow very large, which can affect its performance, slowing down all applications logging to it. It may be necessary to consider a more sophisticated event store like a database. However, we cannot do this with the standard .NET event logging API.
- Every computer now has to have permissions to access the central computer's event logs.
In the following section we develop a library that alleviates the above problems.
A distributed event logging library
The amount of code in this library is surprisingly small considering the amount of work it does. Let us first get a high level view of the classes involved and their relationships.
Every event is described by an
Event class. Every application that needs to log events must define its event source described by the
EventSource class. Thus, while
EventSource captures all data about the source,
Event captures data about the individual events.
Every application logs events using the
LocalEventLog class which is implemented as a singleton. The
LocalEventLog does the job of buffering the logs of the events as they are generated by the application. This buffer is maintained as a hashtable of
EventCollection buffers data from one
EventSource only. Thus the
LocalEventLog contains as many
EventCollection as there are
EventSource. When the buffer for a particular
EventCollection is full it downloads all events in its buffer to a
GlobalEventLog which is running on a remote machine. The communication between the local log and the global log is implemented using remoting. The
GlobalEventLog then persists the events as necessary. It can persist them in one or more event stores if required.
Now let's look at the code for these classes.
Created: January 16, 2003
Revised: January 16, 2003