Here's another example of extending the ILog interface to accept
additional parameters:

http://tinyurl.com/cpz5o
http://cvs.apache.org/viewcvs.cgi/logging-log4net/extensions/net/1.0/log4net.Ext.EventID/cs/src/IEventIDLog.cs?view=markup

If you made an overload like this:
 
 log.Error(string, Exception, params object[]);

You could check the object array to see if it contained an even number
of elements. Elements having an even index (0, 2, 4, etc.) would be
keys and elements having an odd index (1, 3, 5, etc.) would be values:

 log.Error("An exception occured", e, 
  "LogData", myData,
  "LogException", e.Message,
  "Hello", "World");

 // untested
 if (args % 2 == 0)
 {
  for (int i=0;i<args.Length-2;i+=2)
  {
   loggingEvent.Properties[args[i]] = args[i+1];
  }
 }

That code looks cleaner to me plus you're now able to pass in objects.

Sometimes I wonder why the MDC (or ThreadContext) doesn't support this
style of (IDisposable?) notation:

 using(log4net.MDC.Set("LogData", myData)
 using(log4net.MDC.Set("LogException", e)
 {
   log.Info("An exception occured.");
 }

That may or may not be easier to read. I believe NDC calls support that
notation. I'm sure there's some good reason why that syntax isn't
supported :-)

- Ron

--- Frode Breimo <[EMAIL PROTECTED]> wrote:

> 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