Log4Net is certainly one of the most important instrumentation library  for logging. Let’s see how to extend, writing a custom formatter for exceptions. Exceptions are important things to log, and it is important to log more information as possible, here is how can you write a simple class to log exception

public class ExceptionLayoutExtended : log4net.Layout.LayoutSkeleton { private PatternLayout patternLayout; PatternLayout PatternLayout { get { return patternLayout ?? (patternLayout = new PatternLayout(Pattern)); } } public ExceptionLayoutExtended() { this.IgnoresException = false; } public String Pattern { get; set; }

As you can see the class must inherit from LayoutSkeleton base class, then I insert a property of type PatternLayout, we will see shortly how it will be used, for now notice that it use lazy construction to actually create the object only at first access, and it pass it a property called Pattern

This is written in C# 3.0, so I can use the short form to define properties. The core of the logging is in the Format() Method.

1 override public void Format(TextWriter writer, LoggingEvent loggingEvent) { 2 if (loggingEvent == null) { 3 throw new ArgumentNullException("loggingEvent"); 4 } 5 ; 6 String header = String.Empty; 7 writer.Write("\n-EXCEPTION EXTENDED LOG START"); 8 //writer.Write("\nBASE MESSAGE:" + loggingEvent.MessageObject); 9 PatternLayout.Format(writer, loggingEvent); 10 Exception curEx = loggingEvent.ExceptionObject; 11 12 while (curEx != null) { 13 writer.Write(header + "\nExceptionMessage: "); 14 writer.Write(header + curEx.Message); 15 writer.Write(header + "\nExceptionType: "); 16 writer.Write(header + curEx.GetType().FullName); 17 18 writer.Write(header + "\nStackTrace: "); 19 if (curEx.StackTrace != null) { 20 writer.Write(header + curEx.StackTrace.ToString()); 21 } 22 curEx = curEx.InnerException; 23 if (curEx != null) { 24 writer.Write("\n" + header + "INNER EXCEPTION"); 25 header += new string('-', 4); 26 } 27 } 28 writer.Write("\nEXCEPTION EXTENDED LOG END"); 29 30 }

This is a very simple way to format the exception, first of all I write an header (line7) then I use the log4Net class PatternLayout to write a formatted header, then I begin to log some information from exception object. At each iteration I goes deeper into exception hierarchy dumping information for the innerException object, until I found a null innerExcception.

In the configuration file now I can use my new layout in this way

<appender name="ExceptionAppender" type="log4net.Appender.FileAppender"> <param name="File" value="Exceptions.txt" /> <param name="AppendToFile" value="true" /> <layout type="mynamespace.ExceptionLayoutExtended, MyAssembly" > <param name="Pattern" value="%d - %exception% Detail:%m%newline" /> </layout> </appender>

As you can see I created a new appender of type FileAppender, the interesting part is in the layout property: I put my new layout class in type, and then I set a param of name Pattern with value %d – %exception% Detail:%m%newline. With such a definition the log4net configurator look into my ExceptionLAyoutExtended class for a property named Pattern and set it with the value specified in the configuration. Into my layout class I simply use the base PatternLayout class to use the familiar and standard notation usable with log4Net.

Code Sample

Alk.

Tags:

9 Responses to “Writing a custom formatter for log4net”

  1. Hi alkampfer.
    Thanks for Writing a custom formatter for log4net.
    But may i know how can i use _ExceptionLayoutExtended.cs file in my asp.net application ?
    Should i only add this class under App_Code folder ?
    Please reply.

    Thanks in Advance.
    Pushkar

  2. You sould put in a dll (a dll project) it is the best solution.

    alk.

  3. Hi….
    Is it ” \log4net-1.2.10\src\Appender ” ?
    I m sorry…I m not getting you…
    Can you please elaborate ?

  4. Yo need only to take the source sample, take the ExceptionLayoutExtended class file, and copy into a dll project or into the app_code.

    Then you need to reference in log4net configuration

    remember to substitute mynamespace with the correct namespace and myassembly

    alk.

  5. Hi
    I have downloaded the source code of log4net-1.2.10.
    I have added the ExceptionLayoutExtended.cs file in \log4net-1.2.10\src\Layout folder…put in right place, think so.
    And now i tried to build in Debug mode its run successfully but when i tried to build in Release mode it show me error..

    “Error 1 Cryptographic failure while signing assembly ‘D:\Log 4 Net\log4net-1.2.10\src\obj\Release\log4net.dll’ — ‘Error reading key file ‘..\..\..\log4net.snk’ — The system cannot find the file specified. ‘ log4net ”

    There is online in AssemblyInfo.cs
    [assembly: AssemblyKeyFile(@"..\..\..\log4net.snk")]

    Now what is the problem ?

  6. ok i have solved the snk key problem but log4net can not send the email from my webiste…
    btw thanks alk.

  7. Check the smtp :) usually the erorr is there.

  8. ok i can now send email successfully using log4net but i have problem that if i make new dll for my custom setting how can i add it in my Assembly ?

    Like i have added this http://www.codeproject.com/KB/.....ender.aspx

    But gives me exception..

    [HHR.log4net.Appender.NonBufferedSmtpAppenderWithSubjectLayout, HHR.log4net]
    log4net:ERROR XmlHierarchyConfigurator: Could not create Appender [SmtpAppender] of type [HHR.log4net.Appender.NonBufferedSmtpAppenderWithSubjectLayout, HHR.log4net]. Reported error follows.
    System.IO.FileLoadException: Could not load file or assembly ‘log4net, Version=1.2.9.0, Culture=neutral, PublicKeyToken=b32731d11ce58905′ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0×80131040)
    File name: ‘log4net, Version=1.2.9.0, Culture=neutral, PublicKeyToken=b32731d11ce58905′
    at System.RuntimeTypeHandle._GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName)
    at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
    at System.RuntimeType.PrivateGetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
    at System.Type.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase)
    at log4net.Util.SystemInfo.GetTypeFromString(Assembly relativeAssembly, String typeName, Boolean throwOnError, Boolean ignoreCase)
    at log4net.Util.SystemInfo.GetTypeFromString(String typeName, Boolean throwOnError, Boolean ignoreCase)
    at log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseAppender(XmlElement appenderElement)

  9. Always read carefully the exception, here I see
    Could not load file or assembly ‘log4net, Version=1.2.9.0
    probably the log4net.dll is not present in the folder, or is from a different version.

    alk.