Search code examples
c#log4netikvm

How can I take over writing an exception in log4net


We have a large Java application that we convert to .NET using IKVM. All of the log4j calls in it call a log4j wrapper we created that calls log4net. Mostly it works great.

But we have one problem - the logging does not give the stack trace or InnerException(s). I believe the problem is the .NET Exception.ToString() provides all that information while the Java Throwable.toString() is basically the Exception.Message.

So where log4net calls Exception.ToString(), I need to replace that for any exception that inherits from java.lang.Throwable to create the string. How can I do this?


Solution

  • Before calling Exception.ToString(), Log4net looks whether a custom IObjectRenderer has been registered for an Exception (as it also does for any other type).

    In order to get a custom Exception output, you need to create and register a custom IObjectRenderer.

    The one here below will output the Exception in uppercase.
    You are free to build any error message string representation which you pass to writer.Write.

    namespace PFX
    {
        public class MyExceptionRenderer : IObjectRenderer
        {
            public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer)
            {
                Exception exception = obj as Exception;
                // Format the error message as pleased here.
                String error = exception.ToString().ToUpper();
                writer.Write(error);
            }
        }
    }
    

    You register the MyExceptionRenderer in your Log4net configuration as shown below.

    <log4net>
        <appender name="consoleAppender" type="log4net.Appender.ConsoleAppender" >        
            <layout type="log4net.Layout.PatternLayout">            
                <conversionPattern value="%date | %logger | %level | %message | %exception%n" />
            </layout>
        </appender>
        <root>
            <level value="All" />        
            <appender-ref ref="consoleAppender" />
        </root>
    
        <renderer renderingClass="PFX.MyExceptionRenderer"
                  renderedClass="System.Exception" />
    </log4net>
    

    The code below

    var logger = LogManager.GetLogger("AppLog");
    var exception = new ApplicationException("Ooops");
    logger.Error("An error occured.", exception);
    

    will have the following log output.
    Notice that the exception is in full caps.

    2019-05-08 21:52:22,855 | AppLog | ERROR | An error occured. | SYSTEM.APPLICATIONEXCEPTION: OOOPS