2

I have been using log4net to capture any exceptions which occur during my applications running, which is working perfectly, I then created my own static Method which was responsible for capturing the failed XML object which was intended to provide further reading to compliment the log entry.

public static void WriteReceiptToXml(Exception ex, string XmlReceipt)
{
    if (XmlReceipt != null)
    {
        string filename = ConfigurationManager.AppSettings["XmlReceiptPath"] + "/ReceiptXml" + DateTime.Now.ToString("ddMMyyhhmmss") + ".xml";
        File.WriteAllText(filename, XmlReceipt);
        Logger.Error(string.Format("The Xml Receipt was written to {0}", filename));
    }

    else
        Logger.Error("The Xml Receipt was empty so no document was created. Please reference the Payment request XML");
}

This worked well, however a more experienced colleague suggested that this was abit of a code smell and that I was effectively re-inventing the wheel, as I am already using log4net this task should be handled by it too.

At this point I created a new appender in the Web.config file (below) and filtered it on the INFO level, what I realised then was that as soon as I ran the application, log4net would create the XML file regardless of whether the catch block caught the exception and would leave it empty if no error occurred, which is obviously not what I want.

<appender name="ReceiptXmlAppender" type="log4net.Appender.FileAppender" >
  <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
  <file type="log4net.Util.PatternString" value="App_Data/ReceiptXml/Receipt-%date{yyyy-MM-dd_HH-mm-ss}.xml"/>
  <appendToFile value="false" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%m" />
  </layout>
  <filter type="log4net.Filter.LevelRangeFilter">
    <param name="LevelMin" value="INFO"/>
    <param name="LevelMax" value="INFO"/>
  </filter>
</appender>

In summary what I want is:

  • log4net to only create the XML upon the INFO method being called in my catch block
  • 1 file to be created every time I call LOG.INFO
  • The file must be datetime stamped
  • I need to know the file name of the XML document created so that I can append this to actual log file as a supplement to the stack trace.
JsonStatham
  • 9,770
  • 27
  • 100
  • 181
  • 1
    `FileAppender+MinimalLock` should only open the file to write when it needs to. – general exception May 13 '14 at 12:56
  • Yes I thought this but I can see the file is created as soon as the application is run regardless of whether the error occurs, then I am left with the empty XML when I want this to be created ONLY when the catch block executes. – JsonStatham May 13 '14 at 13:08
  • This question seems to back up my opinion that I shouldn't be using log4net to do this, as I am technically not 'logging' the XML file, but saving it as a supplement: http://stackoverflow.com/questions/2533403/log4net-how-to-disable-creation-of-empty-log-file-on-app-start – JsonStatham May 13 '14 at 13:13

1 Answers1

0

If you use the basic FileAppender or one of its derivatives you are out of luck; the file is created as soon as the appender is initialized in the ActivateOptions() method. From what I see you need a custom FileAppender that will handle all your business rules. It would need to

  • override the default ActivateOptions method to prevent file creation
  • override the Append method to create a new timestamped file when a message is logged
  • use data passed in the LoggingEvent class (you have some properties available on the class) to retrieve the filename; you have to determine the filename before logging.

Unless you want to benefit from behavior it already implements(impersonation for example), I'd recommend skipping inheritance from the FileAppender class and inherit directly from the TextWriterAppender class.

samy
  • 14,832
  • 2
  • 54
  • 82