Я бы предложил написать свой собственный Appender для размещения этой логики. Appender может быть использован в качестве оболочки для другого Appender (может быть, SmtpAppender?). ForwardingAppender выглядит как хороший пример «упаковщика» Appender. При поступлении каждого сообщения журнала применяйте логику времени и серьезности. Если ваши критерии удовлетворены, перешлите сообщение «завернутому» заявителю.
В качестве альтернативы этот Appender может содержать собственную логику для генерации и отправки электронной почты (или любую другую схему уведомлений, которую вы хотите использовать).
Этот Appender можно настроить с помощью стандартного механизма конфигурации log4net (app.config, отдельная конфигурация и т. Д.), Чтобы можно было настраивать временной интервал, уровень ошибок, количество ошибок.
Вот идея, как что-то подобное может быть реализовано как Appender:
public class MultiThresholdNotifyingAppender : AppenderSkeleton
{
private Queue<LoggingEvent> loggingEventQueue = new Queue<LoggingEvent>();
private DateTime windowStart;
public Level LevelThreshold { get; set; }
public TimeSpan WindowLength { get; set; }
public int HitThreshold { get; set; }
public void Append(LoggingEvent loggingEvent)
{
if (loggingEvent.Level < LevelThreshold)
{
if (loggingEventQueue.Count == 0) return;
if (loggingEvent.TimeStamp - windowStart) >= WindowLength)
{
//Error level is less than threshold and the time window has elapsed. Remove any queued LoggingEvents
//until all LoggingEvents in the queue fall within the time window.
while (loggingEventQueue.Count > 0 && loggingEventQueue.Peek().TimeStamp - windowStart >= WindowLength)
{
loggingEventQueue.Dequeue();
}
windowStart = loggingEventQueue.Peek().TimeStamp;
return;
}
}
//If we got here, then the Error level is >= the threshold. We want to save the LoggingEvent and we MIGHT
//want to notify the administrator if the other criteria are met (number of errors within time window).
loggingEventQueue.Enqueue(loggingEvent);
//If this is the first error in the queue, start the time window.
if (loggingEventQueue.Count == 1) windowStart = loggingEvent.TimeStamp;
//Too few messages to qualify for notification.
if (loggingEventQueue.Count < HitThreshold - 1) return;
//Now we're talking! A lot of error messages in a short period of time.
if (loggingEvent.TimeStamp - windowStart >= WindowLength)
{
//Build a notification message for the administrator by concatenating the "rendered" version of each LoggingEvent.
string message = string.Join(Enviroment.NewLine, loggingEventQueue.Select(le => le.RenderedMessage));
SendTheMessage(message);
}
//After sending the message, clear the LoggingEvents and reset the time window.
loggingEventQueue.Clear();
windowStart = loggingEvent.TimeStamp;
}
public void Append(LoggingEvent[] loggingEvents)
{
foreach (var le in loggingEvents)
{
Append(le);
}
}
}
Идея состоит в том, чтобы настроить ваши пороговые значения (возможно, вместе с методом уведомления) в приложении. Сконфигурируйте свои регистраторы так, чтобы они отправляли свои сообщения этому приложению, в дополнение к любым другим добавителям, которым вы хотите их отправлять (EventLog, File и т. Д.). По мере прохождения каждого сообщения журнала этот аппендер может проверить его в контексте настроенных пороговых значений и при необходимости отправить уведомление.
В этом коде вполне могут быть проблемы с многопоточностью (если только log4net не решит эту проблему за вас), поэтому вам может потребоваться блокировка при доступе к очереди.
Обратите внимание, что этот код не был скомпилирован и не был протестирован.
См. Эту ссылку для некоторых примеров пользовательских приложений в репозитории log4net:
http://svn.apache.org/viewvc/logging/log4net/trunk/examples/net/2.0/Appenders/