NLog email buffering wrapper





5.00/5 (1 vote)
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:
<extensions>
<add assembly="LevelTriggeredBufferingWrapper"/>
</extensions>
Second, use the wrapper:
<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.