Nicko, thank you for your suggestion with the event message properties. My goal of logging complex event data (which Alejandro also mentioned in his post) can be solved using those properties, but in slightly different way.

Instead of manually adding properties at ILog.Info() call, I propose a forwarding appender that can take any message object, extract all public properties and add them to the properties hashtable. The code i wrote is inheriting the ForwardingAppender class.

// -- Usage example --
class DataMessage
{
 DataMessage( string name, int age ) { Name=name; Age=age; }
 public string Name;
 public int Age;
 public override string ToString()
 { return string.Format("{0} ({1})", Name, Age) ;  }
}
 . . .
logger.Info( new DataMessage( "Bob", 40 ) );


configuration file:

<appender name="DataPropertyAdder" type="LoggerExtensions.PropertyAdderAppender, LoggerExtensions">
<appender-ref ref="FileAppender" />
</appender>



A simple configuration file change will allow any complex logging, such as forwarding those properties into text / xml / sql database by using standard pattern layout class.


My biggest concern is how to do property rendering - properties are added as is to the hashtable, and i did not find a good way to specify formating. ToString() of each object will be used, but for example XmlLayout has no code to do xml property encoding.

Here's the PropertyAdder appender class.


// Submitted by Yuri Astrakhan (zapodlo at gmail dot com) for Log4net project.
//
/// <summary>
/// This appender modifies <see cref="LoggingEvent"/> by adding
/// all public properties of the message object to
/// the <see cref="LoggingEvent.Properties"/> hashtable
/// and forwards the event to the next appenders.
/// </summary>
public class PropertyAdderAppender : ForwardingAppender
{
#region Public Instance Constructors


/// <summary>
/// Initializes a new instance of the <see cref="PropertyAdderAppender" /> class.
/// </summary>
public PropertyAdderAppender()
{}


 #endregion

 #region  Override implementation  of ForwardingAppender

 ///  <summary>
 ///  This method  is called by the <see cref="AppenderSkeleton.DoAppend"/>
 ///  method.
 ///  </summary>
 ///  <param name="loggingEvent">The event to  log.</param>
 override protected void  Append(LoggingEvent  loggingEvent)
 {
   // TODO: accessing indexed properties
   // TODO: accessing sub-properties: a.b.c
   // TODO: implement attribute-based property  filtering
   // TODO: implement customizable  property name prefix

   // NOTE: objects do  not  need to  be rendered  at this  stage,
   // besides,  RenderMap is not easily  accessible from  here.

   foreach( PropertyInfo propInfo in loggingEvent.MessageObject.GetType().
     GetProperties( BindingFlags.Instance | BindingFlags.Public ))
   {
     if(  propInfo.CanRead )
       loggingEvent.Properties[propInfo.Name] =
         propInfo.GetValue(loggingEvent.MessageObject, null);
   }

   foreach( FieldInfo fldInfo in loggingEvent.MessageObject.GetType().
     GetFields( BindingFlags.Instance | BindingFlags.Public ))
   {
     loggingEvent.Properties[fldInfo.Name] =
       fldInfo.GetValue(loggingEvent.MessageObject);
   }

   base.Append(loggingEvent);
 }

 #endregion
}

_________________________________________________________________
Is your PC infected? Get a FREE online computer virus scan from McAfee� Security. http://clinic.mcafee.com/clinic/ibuy/campaign.asp?cid=3963




Reply via email to