Click here to Skip to main content
15,860,861 members
Articles / Programming Languages / C#
Tip/Trick

NLog email buffering wrapper

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
19 Dec 2010CPOL 21.3K   2   4
An NLog target wrapper to pass on log events when triggered by an event with a specified log level
I needed an extension to NLog to buffer log output for a MailTarget and only send it when an event with Fatal level arrives. In other words, it will email me the whole buffer when the program crashes so that I get some context with the crash event.

I wrote a LevelTriggeredBufferingWrapper to achieve that. Here's the significant bit:

using System.ComponentModel;
using NLog;
using NLog.Common;
using NLog.Targets;
using NLog.Targets.Wrappers;

namespace LevelTriggeredBufferingWrapper
  {
  [Target("LevelTriggeredBufferingWrapper", IsWrapper = true)]
  public class LevelTriggeredBufferingWrapper : WrapperTargetBase
    {
    LogLevel triggerLevel = LogLevel.Fatal;
    LogEventInfoBuffer buffer;

    public LevelTriggeredBufferingWrapper()
      : this(null)
      {
      }

    public LevelTriggeredBufferingWrapper(Target wrappedTarget)
      : this(wrappedTarget, 100)
      {
      }

    public LevelTriggeredBufferingWrapper(Target wrappedTarget,
                                          int bufferSize,
                                          string triggerLevel = "Fatal")
      {
      try
        {
        this.triggerLevel = LogLevel.FromString(triggerLevel);
        }
      catch { /* use default trigger level */ }

      WrappedTarget = wrappedTarget;
      BufferSize = bufferSize;
      }

    /// <summary>
    /// Gets or sets the number of log events to be buffered.
    /// </summary>
    [DefaultValue(100)]
    public int BufferSize { get; set; }

    /// <summary>
    /// Gets or sets the trigger level. Any event with a level equal to
    /// or greater than the trigger level will cause the whole buffer of
    /// events to be passed to the wrapped target
    /// </summary>
    /// <value>The trigger level.</value>
    [DefaultValue("Fatal")]
    public string TriggerLevel
      {
      get { return triggerLevel.ToString(); }
      set { triggerLevel = LogLevel.FromString(value); }
      }

    protected override void FlushAsync(NLog.Common.AsyncContinuation asyncContinuation)
      {
      // do nothing
      }

    protected override void InitializeTarget()
      {
      base.InitializeTarget();
      this.buffer = new LogEventInfoBuffer(this.BufferSize, false, 0);
      }

    protected override void Write(NLog.Common.AsyncLogEventInfo logEvent)
      {
      WrappedTarget.PrecalculateVolatileLayouts(logEvent.LogEvent);

      buffer.Append(logEvent);
      if (logEvent.LogEvent.Level >= triggerLevel)
        {
        AsyncLogEventInfo[] events = buffer.GetEventsAndClear();
        WrappedTarget.WriteAsyncLogEvents(events);
        }
      }
    }
  }


You can use it to wrap any target you like but I think it's most useful for an email target.
You need to modify the NLog.config file.
First add a reference to the assembly with the wrapper:

XML
<extensions>
  <add assembly="LevelTriggeredBufferingWrapper"/>
</extensions>


Second, use the wrapper:

XML
<target name="gmailwrapper" xsi:type="LevelTriggeredBufferingWrapper">
  <BufferSize>100</BufferSize>
  <TriggerLevel>Fatal</TriggerLevel>
  <target name="mail" xsi:type="Mail" >
    <!-- whatever else you need to configure the mail target -->
  </target>
</target>


Those BufferSize and TriggerLevel parameters are not really necessary - they are the default values, but you can change the values if you want.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
England England
Started my career as an electronics engineer.

Started software development in 4004 assembler.

Progressed to 8080, Z80 and 6802 assembler in the days when you built your own computer from discrete components.

Dabbled in Macro-11 and Coral66 by way of a small digression.

Moved on to C, first on Z80s and then on PCs when they were invented.

Continued to C++ and then C#

Now working mostly in C# and XAML while maintaining about half a million lines of C++

Comments and Discussions

 
QuestionFull sample Pin
kiquenet.com14-May-15 1:00
professionalkiquenet.com14-May-15 1:00 
QuestionNice use of wrapper Pin
Waterpepper26-Jan-15 1:40
Waterpepper26-Jan-15 1:40 
GeneralReason for my vote of 5 Just what I was looking for. Perfect... Pin
Simon Hughes11-Mar-11 23:50
Simon Hughes11-Mar-11 23:50 
GeneralGood work Pin
Abdul Quader Mamun16-Dec-10 9:38
Abdul Quader Mamun16-Dec-10 9:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.