How to write your own Filter
Why would I want to write a Filter?
Filters are a way to eliminate unnecessary logging messages and prevent them from reaching log targets. NLog comes with pre-defined filters that operate on string layouts and support most common operators. You need your own filter if none of the provided filters are suitable for your purpose.
How to write a filter?
It's really easy. Create a class that inherits from NLog.Filter
and override the Check() method. This method should return one of the following:
FilterResult.Neutral- The filter doesn't want to decide whether the message should be logged. Further filters (if any) should be invoked to check.FilterResult.Ignore- The message should NOT be loggedFilterResult.Log- The message should be logged. No further filters will be invoked.
Typically it's up to the user to decide what to do with the message after the filter matches.
Each filter has a Result that contains user-requested filter result for such a case. Filters
that would like to support user-configurability should return Result or FilterResult.Neutral.
Example
This is an example filter that eliminates messages sent between the specified hours.
csc.exe /t:library /out:MyAssembly.dll /r:NLog.dll MyFirstFilter.cs
using System;
using System.Text;
using NLog;
namespace MyNamespace
{
[Filter("hourRange")]
public sealed class HourRangeFilter: Filter
{
private int _fromHour = 0;
private int _toHour = -1;
public int FromHour
{
get { return _fromHour; }
set { _fromHour = value; }
}
public int ToHour
{
get { return _toHour; }
set { _toHour = value; }
}
protected override FilterResult Check(LogEventInfo ev)
{
if (ev.TimeStamp.Hour >= FromHour && ev.TimeStamp.Hour <= ToHour)
return Result;
else
return FilterResult.Neutral;
}
}
}How to use the newly created layout renderer?
It's easy. Just put the renderer in a DLL and reference it from the the config file using the <extensions /> clause as described here.
Configuration file example
This example causes all messages between 10:00 and 12:59 to be ignored. Simple isn't it?
<nlog>
<extensions>
<add assembly="MyAssembly"/>
</extensions>
<targets>
<target name="console" type="Console"/>
</targets>
<rules>
<logger name="*" minLevel="Info" appendTo="console">
<filters>
<hourRange fromHour="10" toHour="12" action="Ignore"/>
</filters>
</logger>
</rules>
</nlog>
How to pass configuration options to the filter?
Consider the above example. There are properties called "FromHour" and "ToHour" that do just that. Having a public property that sets the required configuration parameters is enough for NLog to use it. Each attribute that you put in the filter definition gets passed to the appropriate public property. NLog takes care of the appropriate conversions necessary so that you can use integer, string, datetime, boolean parameters. The parameters are case-insensitive.
<filters> ... <hourRange fromHour="10" toHour="12" action="Ignore" /> ... </filters>sets the FromHour property to 10 and ToHour to 12 during configuration. To pass more parameters, just use more attributes:
<filters> ... <hourRange p1="" p2="" p3="" p4="" pN="" action="Ignore" /> ... </filters>Do I really need to create a separate DLL?
Not really. You can use FilterFactory.AddFilter() to register your layout renderer programmatically. Just be sure to to it at the very beginning of your program before any log messages are written. It should be possible to reference your EXE using the <extensions /> clause.
static void Main(string[] args)
{
FilterFactory.AddFilter("MyFirst", typeof(MyNamespace.MyFirstFilter));
// start logging here
}

