I've been using nLog within the delivery stack at work since I started automating the processes a few months ago. It works well the majority of the time, and I've got it logging usage stats as well as errors/debug information making use of the targetting to be able to direct different levels of issues to different logs. When a serious error occurs, then it emails to let me know. Unless we've had a network outage, in which case the email goes missing. Which isn't great.

I want to get it to retry until it suceeds ideally. But I found the documentation on using a RetryWrapper a bit sketchy. Consequently, I'm writing up my findings for myself.

I first of all found this which I used as a base for my targets section:

<targets>
  <target xsi:type="RetryingWrapper" name="String" retryDelayMilliseconds="Integer" retryCount="Integer">
    <target xsi:type="wrappedTargetType" ...target properties... />
  </target>
</targets>

I found it difficult to determine which parts of this should be replaced and which shouldn't. For instance the xsi:type="wrappedTargetType" bit should, perhaps obviously, be replaced with the actual type, i.e. xsi:type="File" or xsi:type="Mail". If you try and run it using xsi:type="wrappedTargetType" you'll get a "Target cannot be found: 'wrappedTargetType'" error message.

I decided that rather than starting to update the config for my applications, I'd start simply, so created a new solution and used the sample tutorial code to exercise nLog. I got a simple version working as follows (with a lot of help from the worked example.  It's worth noting that there are a lot of simple example configs available):

<targets>
  <target xsi:type="RetryingWrapper" name="errorLog" retryCount="5" retryDelayMilliseconds="5000" >

    <target xsi:type="file" fileName="C:\Logs\${date:format=yyyy-MM-dd}.log"  />       
  </target>
</targets>
<rules>
  <logger name="*" minlevel="Error" writeTo="errorLog" />
</rules>

I recommend setting internal logging on whilst debugging/configuring nLog. The nLog section of my config file currently looks like:

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       internalLogFile="C:\logs\nLogInternals.txt"
       internalLogLevel="Debug" >

which means it's writing all it's settings to the nLogInternals.txt file, which allows me to check that retry functionality is being set up in a manner I'd expect. Obviously this needs to be removed before deploying for real otherwise it'll end up creating huge log files all over the place.

During my research I'd also stumbled across the concept of default-wrappers (via this excellent stackoverflow answer) which seemed to be what I wanted but I couldn't work out how to use them initially - possibly because I first attempted to plug it in to my more complicated, real, configuration. I don't want to change the retry information on a target by target basis. so by using a default-wrapper of type RetryingWrapper I seem to be able to wrap all of the targets within a RetryingWrapper in the same way as if I explicitly specified it (or at least that's what both my nLogInternals.txt file and the documentation both seem to suggest).

So, my (simplified) final solution looks like the following:

<targets>
      <default-wrapper xsi:type="RetryingWrapper" retryCount="5" retryDelayMilliseconds="5000" />      
      <target xsi:type="file" fileName="C:\Logs\${date:format=yyyy-MM-dd}.log" name="errorLog" />
      <target xsi:type="file" fileName="C:\Logs\FATAL-${date:format=yyyy-MM-dd}.log" name="fatalLog" />
    </targets>
 
    <rules>
      <logger name="*" minlevel="Warn" writeTo="errorLog" />
      <logger name="*" minlevel="Fatal" writeTo="fatalLog" />
    </rules>

which seems to do what I think it should. Now to update all the applications in my stack to use these settings.