Hi

I've made a couple of customizations to log4net and would like to hear people's opinion on my solution.

When logging I've made extensive use of properties to put data in specific database fields. These properties must (as far as I know) be placed in GlobalContext, ThreadContext or LogicalThreadContext. This can be a bit of a drag since the properties are still active after logging, this results in code like

   log4net.LogicalThreadContext.Properties["LogData"] = myData;
   log4net.LogicalThreadContext.Properties["LogException"] = e.Message;
   log.Error("An exception occured");
   log4net.LogicalThreadContext.Properties.Remove("LogData");
   log4net.LogicalThreadContext.Properties.Remove("LogException");

I got tired of this, so after picking up a few tips and tricks from other threads in this mailing list I decided to make an attempt at customizing Log4Net. I decided to make another overload for each of the logging methods (log.Info, log.Debug etc), an overload that (in addition to a message and an exception) takes in the names and values of the desired properties, and adds them to the logging event itself, thus making them unique for that perticular logging call. What I ended up with was the following additions to LogImpl.cs:

virtual public void Error(object message, Exception exception, string[] propertyNames, string[] propertyValues)
   {
Logger.Log(CustomLoggingEvent(m_levelError, message, exception, propertyNames, propertyValues));
   }


private LoggingEvent CustomLoggingEvent(Level level, object message, Exception exception, string[] propertyNames, string[] propertyValues)
   {
       LogLog.Debug("Creating custom logging event.");
log4net.Core.LoggingEvent loggingEvent = new log4net.Core.LoggingEvent(ThisDeclaringType, Logger.Repository, Logger.Name, level, message, exception);
       try
       {
// Ignore all properties if the two arrays are of different lengths
           if (propertyNames.Length == propertyValues.Length)
           {
               for (int i = 0; i < propertyNames.Length; i++)
               {
                   if (propertyNames[i].Length > 0)
                   {
                       // Add the parameter to the LoggingEvent
loggingEvent.Properties[propertyNames[i]] = propertyValues[i]; LogLog.Debug("Property " + propertyNames[i] + " added to custom logging event, with a value of " + propertyValues[i]);
                   }
               }
           }
       }
       catch (Exception exc)
       {
LogLog.Debug("Error creating custom logging event: " + exc.Message);
       }
       return loggingEvent;
   }


...and in ILog.cs, I added

void Error(object message, Exception exception, string[] propertyNames, string[] propertyValues);


So, instead of the previous code where I added and then removed the properties every time I needed them, I now use the following code to log with properties:

log.Error("An exception occured", e, new string[]{"LogData", "LogException"}, new string[]{myData, e.Message});


This makes logging with properties a lot easier to code, but is it a good solution? I know it's somewhat limited with the arrays being of type string and not Object, but I wanted to keep it simple as a start, and it satisfies my (current) needs. But besides that? Are there any other parts of Log4Net that needs to be altered because of this (it works fine now though), is the way I've solved it good, is the code good? Any advice or criticism (and even praise) would be apreciated.


Regards,
Frode


Reply via email to