PITADEV
Curiosity killed the developer's project.

Setting an EventLogAppender’s Event Source at Runtime

Friday, 17 July 2009 09:37 by aj

I’m switching one of my big frameworks over from a homegrown logging solution to the beautifully simple and powerful log4net.  One of the many conveniences offered with log4net is the ability to log messages to many different message repositories with one call.  Our application requires three logging repositories: a table in our DB2 database, SMTP email, and the event log.  Using the built-in thresholds, the DB2 table receives all messages, while email and the event log only receive Error and Fatal messages.

This particular framework runs under a Windows Service, which uses a Factory to load multiple implementation assemblies that all execute on their own child thread.  Each implementation is responsible for its own set of activities, of course, and the service itself knows only to check the child threads every now and then to make sure they aren’t dead.  Using the default setup for the EventLogAppender, you can set the event source in the configuration by setting the EventLogAppender’s ApplicationName property.  In this case, all of the configuration for log4net is set in the service’s app.config file, which means that the settings for each appender are global to the service.  That’s fine, for most applications, but in this case it would be very convenient to change the event source to something that’s indicative of the specific implementation thread making the logging call, making it much easier to find messages related to a particular implementation.

The obvious way to do this would be to set the ApplicationName property at runtime before each logging call.  However, after much Googling, I wasn’t able to find an example of how to do this.  So I mused and ruminated and muddled about for a while, and eventually started fiddling in the Immediate Window while debugging my test application, attempting to figure out how to access specific appender properties at runtime.  Turns out the solution is simpler than I could have imagined.  Using the excellent tutorials provided by Sir Beefy, I set up my log object like this:

   1: //Console app, global
   2: private static log4net.ILog log;
   3:  
   4: //In void Main()
   5: log4net.Config.XmlConfigurator.Configure();
   6: log = log4net.LogManager.GetLogger(
   7:     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

Then I provided a Log() method in the abstract class that is required for each implementation that looks something like this:

   1: protected void Log(string appName, 
   2:                    string message, 
   3:                    Exception ex, 
   4:                    log4net.Core.Level entryLevel)
   5: {
   6:     //Set the application name of the EventLogAppender
   7:     ((log4net.Appender.EventLogAppender)
   8:         log.Logger.Repository.GetAppenders().Single(
   9:         a => a.Name == "EventLogAppender")
  10:         ).ApplicationName = appName;
  11:     //do whatever else to log the entry
  12: }

That’s it.  It might be a better idea to use a GetType() call to find the Appender of type EventLogAppender and set the ApplicationName property that way, but I don’t think that’s necessary here.  So if you’re looking to change the Event Source at runtime using log4net to an event log, this is one way to do it without having to change the configuration file on the fly.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:  
Categories:   .Net | Tools
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed