title: log4net CSV File Appender Custom Parameters
body: <p>I am currently using log4net for an application I am working on. I have setup a CsvRollingFileAppender but am wonder how I can extend it to log passed parameters. An example would be something along the lines of the following:</p>
  
  <pre><code>log.Info(string.format("{0} - {1} - {2} - {3}", value1, value2, value3, value4));
  </code></pre>
  
  <p>The config for my Appender looks like this</p>
  
  <pre><code>&lt;appender name="CsvRollingFileAppender" type="DataCalcuation.Classes.CsvHeaderOverride"&gt;
    &lt;threshold value="INFO" /&gt;
    &lt;lockingModel type="log4net.Appender.FileAppender+MinimalLock" /&gt;
    &lt;file value="logs/" /&gt;
    &lt;datePattern value="'DataCaclulation'.MM.dd.yyyy'.csv'" /&gt;
    &lt;appendToFile value="true" /&gt;
    &lt;rollingStyle value="Date" /&gt;
    &lt;maxSizeRollBackups value="10" /&gt;
    &lt;maximumFileSize value="5MB" /&gt;
    &lt;staticLogFileName value="false" /&gt;
    &lt;layout type="log4net.Layout.PatternLayout"&gt;
      &lt;header value="DateTime,Level,Location,Message&amp;#13;&amp;#10;" /&gt;
      &lt;conversionPattern value="%date{M/d/yyyy H:mm:ss.fff},%level,%location,%message%newline" /&gt;
    &lt;/layout&gt;
  &lt;/appender&gt;
  </code></pre>
  
  <p>I would like to have it setup to have the headers of </p>
  
  <pre><code> DateTime, Level, Location, PassedValue1, PassedValue2,  .....
  </code></pre>
  
  <p>I have stumbled across a few different articles like the following and wondered if that was the correct approach or if there was a more efficient way</p>
  
  <p>Any insight would be greatly appreciated </p>
  
  <p>I think I have to do something like this
   - <a href="http://element533.blogspot.in/2010/05/mapping-message-object-properties-to.html" rel="nofollow">Mapping message properties to CSV columns using log4net</a></p>
  
  <p>Answer:</p>
  
  <p>As promised here is the code I used to achieve what I was looking to do all credit goes to Steven Padfield whose post I used</p>
  
  <p>I created a class called CsvLogEvent with the items I wanted to capture in the log</p>
  
  <pre><code>public class CsvLogEvent
  {
       public int Value1 {get; set;}
       public string Value2 {get; set;}
       public string Value3 {get; set;}
       public int Value4 {get; set;} 
  }
  </code></pre>
  
  <p>I then used the following format to log the events</p>
  
  <pre><code>private readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  
  log.Info(new CsvLogEvent {
       Value1 = 1,
       Value2 = "Test",
       Value3 = "Log Event",
       Value4 = 0
  });
  </code></pre>
  
  <p>To property format the CSV output I had to create a class to handle the new Pattern</p>
  
  <pre><code>public class CsvPattern : PatternLayout
  {
       public override void Format(TextWriter writer, LoggingEvent loggingEvent)
       {
            if (loggingEvent.MessageObject != null)
            {
                 PropertyInfo[] properties = loggingEvent.MessageObject.GetType().GetProperties();
                 foreach(PropertyInfo prop in properties)
                 {
                      object value = prop.GetValue(loggingEvent.MessageObject, null);
                      loggingEvent.Properties[prop.Name] = value;
                 }
             }
             base.Format(writer, loggingEvent);
       }
  }
  </code></pre>
  
  <p>Then finally setup the appender in your app.config file</p>
  
  <pre><code>&lt;appender name="Test" type="DataCalcuation.Classes.CsvAppender"&gt;
    &lt;threshold value="INFO" /&gt;
    &lt;lockingModel type="log4net.Appender.FileAppender+MinimalLock" /&gt;
    &lt;file value="logs/" /&gt;
    &lt;datePattern value="'DataCaclulation'.MM.dd.yyyy'.csv'" /&gt;
    &lt;appendToFile value="true" /&gt;
    &lt;rollingStyle value="Date" /&gt;
    &lt;maxSizeRollBackups value="10" /&gt;
    &lt;maximumFileSize value="5MB" /&gt;
    &lt;staticLogFileName value="false" /&gt;
    &lt;layout type="DataCalcuation.Classes.CsvPattern"&gt;
      &lt;header value="DateTime,Level,Location,Value1, Value2, Value3, Value4&amp;#13;&amp;#10;" /&gt;
      &lt;conversionPattern value="%date{M/d/yyyy H:mm:ss.fff},%level,%location,%property{Value1},%property{Value2},%property{Value3},%property{Value4}%newline" /&gt;        
    &lt;/layout&gt;
  &lt;/appender&gt;
  </code></pre>
  
  <ul>
  <li><a href="https://sitecorepm.wordpress.com/2011/02/17/adding-custom-parameters-to-the-log/" rel="nofollow">Adding custom parameters to the log</a></li>
  <li><a href="http://jonhilton.net/2008/07/23/log4net-custom-appender/" rel="nofollow">Log4Net Custom Appender</a></li>
  </ul>