3

I am trying to log exceptions into a database with Log4Net. I am using the adonetappender and it does work, but not optimally.

If I configure the exception parameter like this...

<parameter>
  <parameterName value="@exception"/>
  <dbType value="String"/>
  <size value="-1"/>
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%exception"/>
  </layout>
</parameter>

It works but inserts "" instead of null when there is no exception.

I get the same result if I have it like this...

<parameter>
  <parameterName value="@exception"/>
  <dbType value="String"/>
  <size value="-1"/>
  <layout type="log4net.Layout.ExceptionLayout">
    <!-- <key value="exception" /> -->
    <!--<conversionPattern value="%exception"/>-->
  </layout>
</parameter>

But if I have it like this

<parameter>
  <parameterName value="@exception"/>
  <dbType value="String"/>
  <size value="-1"/>
  <layout type="log4net.Layout.RawPropertyLayout">
    <key value="exception" />
  </layout>
</parameter>

It only inserts null values ...

The problem might be coming from that we have a static logging wrapper that always calls

LogManager.GetLogger("[GoodLife.Common.Logging]").Debug(message, e); // e being null if there is no exception. 

Is there a way for me to have it insert nulls if e is null when I call the debug method on the logger?

The log4net documentation on the layouts isn't all that helpful and I got the last configuration from Default values for AdoNetAppender parameter

Community
  • 1
  • 1
Kevin Donde
  • 912
  • 3
  • 15
  • 32

2 Answers2

4

The problem is that the exception is not a property and therefore log4net cannot find anything with the key "exception" and thus you get always null.

In order to solve your problem you can create your own layout converter like this:

public class RawExceptionLayout : IRawLayout
{       
    public virtual object Format(LoggingEvent loggingEvent)
    {
         return loggingEvent.ExceptionObject;
    }       
}
Philipp M
  • 1,877
  • 7
  • 27
  • 38
Stefan Egli
  • 17,398
  • 3
  • 54
  • 75
  • Thanks @Stefan, but I'm not really sure if I see how that creates a property with the key "exception". I'm sure you're right but I just don't understand the answer. – Kevin Donde Jul 23 '13 at 14:56
  • It does not create a property it is a different layout that simply passes through the exception. This way the @exception parameter gets the exception directly. I have to admit that I did not test it, so it could be that you need to convert the exception (if not null) to a string first, but this should be easy to figure out. – Stefan Egli Jul 23 '13 at 15:10
  • You are welcome. I see now why you got confused: I changed the name of the class so that it makes more sense. – Stefan Egli Jul 23 '13 at 16:27
  • @StefanEgli As you already mentioned, if `ExceptionObject` is not null you have to return a string. Thanks. – Andre Hofmeister Nov 12 '14 at 13:28
0

You can also modify the used insert statement by log4net and let sql server do the work for you. This has the benefit of not requiring code changes!

Default sample config:

 <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) 
 VALUES (@log_date, @thread, @log_level, @logger, @message, 
@exception)" />

and my modified insert:

 <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) 
 VALUES (@log_date, @thread, @log_level, @logger, @message, 
case when  @exception &lt;&gt; '' then @exception else null end)" />

notice the required encoding of < and > because it is in xml!

fabsenet
  • 372
  • 2
  • 15