6

There seems to be a lot of information and documentation on how to log extra information when an exception is present, but I am having trouble trying to work out how to create a target that is essentially a honeypot for exceptions. Rather than sifting through various log files trying to see if any exceptions were logged, I'd just like a copy of all exceptions to go to a specific target that writes to an exceptions.log file.

How do I do this?

Nathan Ridley
  • 33,766
  • 35
  • 123
  • 197

2 Answers2

18

I can't say that I have actually tried this, but you might be able to use a when filter and a condition to achieve what you want.

Here is an example from the condition page:

<rules>
    <logger name="*" writeTo="file">
        <filters>
            <when condition="length(message) > 100" action="Ignore" />
            <when condition="equals('${logger}','MyApps.SomeClass')" action="Ignore" />
            <when condition="(level >= LogLevel.Debug and contains(message,'PleaseDontLogThis')) or level==LogLevel.Warn" action="Ignore" />
            <when condition="not starts-with('${message}','PleaseLogThis')" action="Ignore" />
        </filters>
    </logger>
</rules>

To achieve your goal, you might make a filter like this:

<rules>
    <logger name="*" writeTo="file">
        <filters>
            <when condition="length('${exception}') > 0" action="Log" />
        </filters>
    </logger>
</rules>

The idea being that you only want to log the message if the length of the exception string is > 0. Some of the when condition examples used the NLog LayoutRenderer syntax (e.g. ${message}) and some didn't (e.g. message). I'm not sure which is correct or which syntax to use in which situation. The example I posted directly above might cause messages to be logged ONLY if there is an exception present. You should also be able to configure such that your messages to one target are logged "normally" and messages to your "ExceptionHoneypotTarget" are logged only if an exception is present.

Maybe something like this:

<rules>
    <logger name="*" writeTo="ExceptionHoneypot">
        <filters>
            <when condition="length('${exception}') > 0" action="Log" />
        </filters>
    </logger>
    <logger name="*" writeTo="file">
    </logger>
</rules>

As I mentioned early on, I haven't actually tried any of this, but it seems like you should be able to do it, hopefully similar to what showed above.

Alternatively, you could use a FilteringWrapper around your HoneypotTarget. The configuration might look something like this:

<?xml version="1.0" ?>
  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"      
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <targets>
          <target name="Honeypot" xsi:type="FilteringWrapper" 
              condition="length('${exception}')>0">
            <target xsi:type="File" fileName="${basedir}/Honeypot.txt" />
          </target>    
          <target name="normal" xsi:type="File" fileName="${basedir}/Log.txt" />
          </target>
        </targets>    
        <rules>
          <logger name="*" minlevel="Debug" writeTo="Honeypot,normal" />
        </rules>
   </nlog> 

I based the FilteringWrapper example on an example from from here. The way it should work, if my configuration is correct, is that all messages will be logged to "Log.txt" and messages with a non-null exception will be logged to "Honeypot.txt".

Rolf Kristensen
  • 17,785
  • 1
  • 51
  • 70
wageoghe
  • 27,390
  • 13
  • 88
  • 116
  • I tried this solution but I had to enclose the ${exception} in single quotes like this: length('${exception}'). I've submitted at new revision for peer review. – Magnus Lindhe Mar 06 '12 at 09:13
  • The condition is wrong, at least as of 4.5. If a condition evaluates to false, the filter returns `FilterResult.Neutral`. Anything that isn't `FilterResult.Ignore` or `FilterResult.IgnoreFinal` defaults to being written. Rather than checking if it is an exception, check if it isn't and ignore it. This is what Ymir's answer does. – bgfvdu3w Apr 21 '18 at 03:00
8

Please note that if you want only exceptions your filter should be:

    <when condition="length('${exception}') = 0" action="Ignore" />
Ymir
  • 300
  • 3
  • 11