Currently have a log4net filter like below. This filter shouldnt allow same message to be logged over a certain interval. However, messages are certain getting logged. Source: Log4net, eliminate duplicate messages
public class UniqueLogFilter : FilterSkeleton
{
private string lastMessage = null;
private List<Tuple<DateTime, string>> lastMessages = new List<Tuple<DateTime, string>>();
public int timeWindow { get; set; } = 0;
public bool lastOnly { get; set; } = false;
public override FilterDecision Decide(LoggingEvent loggingEvent)
{
if (lastOnly)
{
if (lastMessage == loggingEvent.RenderedMessage)
{
return FilterDecision.Deny;
}
lastMessage = loggingEvent.RenderedMessage;
return FilterDecision.Accept;
}
if (timeWindow <= 0)
return FilterDecision.Accept;
// Removes old messages
lastMessages.RemoveAll(m => m.Item1 < DateTime.Now.AddSeconds(0 - timeWindow));
if (!lastMessages.Any(m => m.Item2 == loggingEvent.RenderedMessage))
{
lastMessages.Add(new Tuple<DateTime, string>(loggingEvent.TimeStamp, loggingEvent.RenderedMessage));
return FilterDecision.Accept;
}
return FilterDecision.Deny;
}
This is the App.Config:
<log4net>
<appender name="FileAppender" type="log4net.Appender.FileAppender,log4net">
<file value="Logs\\EmailWatcher.log" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d{MM-dd hh:mm:ss} [%thread] %level %logger - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="FATAL" />
</filter>
</appender>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Logs\\" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d{dd-MM-yyyy hh:mm:ss} [%thread] %level %logger - %message%newline" />
</layout>
<datePattern value="'EmailWatcher.'dd.MM.yyyy'.log'" />
<staticLogFileName value="false" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="5MB" />
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="INFO" />
<levelMax value="WARN" />
</filter>
<filter type="CPVEmailWatcher.UniqueLogFilter">
<loggerToMatch value="RollingLogFileAppender" />
<timeWindow value="1800" />
<!--(30 min interval)-->
<lastOnly value="false" />
</filter>
</appender>
<appender name="ErrorLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="Logs\\" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p%d{ yyyy-MM-dd HH:mm:ss} – [%thread] %m method: %method %n stacktrace: %stacktrace{5} %n type: %type %n line: %line %n" />
</layout>
<datePattern value="'EmailWatcher.'dd.MM.yyyy'.log'" />
<staticLogFileName value="false" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="5MB" />
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="ERROR" />
<levelMax value="FATAL" />
</filter>
<filter type="CPVEmailWatcher.UniqueLogFilter">
<loggerToMatch value="ErrorLogFileAppender" />
<timeWindow value="1800" />
<!--(30 min interval)-->
<lastOnly value="false" />
</filter>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="RollingLogFileAppender" />
<appender-ref ref="ErrorLogFileAppender" />
</root>
The
Decidemethod of theUniqueLogFilterdoesn't get executed, because in the filter hierarchy the topLevelRangeFilteraccepts the event if it matches its condition instead of passing it to the next filter, theUniqueLogFilter.In order to let the
UniqueFilterdecide, you have to setAcceptOnMatchtoFalseon theLevelRangeFilter.With this setting, you'll notice that the
UniqueLogFiltergets executed while debugging.The filter setup looks like below.