I am trying to configure a smtp appender in the log4net.config file that I have. The problem is that I have looked all over the internet and cannot find how to send an email when an error occurs with all the other log information included such as info, debug, error, fatal. Only when the application ends (NOT every time an ERROR occurs).
So I only want to receive this email when: The application ends + With all the log information (DEBUG, INFO, ERROR, FATAL) + Only if an ERROR has occured.
Elaborating some more this is because of the way I handle my exceptions in c sharp, with multiple level handling all over the place and so if an error occurs no matter how many times I only want to receive one email. Also I do not want to use multiple logs, but rather just one in root.
Thanks.
SmtpAppender
cannot accomplish this on its own. So what I did was create another appender that to an appender of type MemoryAppender
. I set a threshold on this logger to only include messages that should trigger the SmtpAppender
, e.g. Error
. We use this to later determine if we want to send the email which has more levels logged.
We don't actually care about the messages in the MemoryAppender
--we just care that it contains messages at the end. The messages we get via email actually come from the SmtpAppender
.
At the end of my program I check the memory appender to see if its GetEvents() contains any events. If so, I do not stop the SmtpAppender
from running normally.
Log4Net configs for both appenders:
<appender name="ErrorHolder" type="log4net.Appender.MemoryAppender" >
<onlyFixPartialEventData value="true" />
<!-- if *any* message is logged with this level, the email appender will
be used with its own level -->
<threshold value="ERROR" />
</appender>
<appender name="Email" type="log4net.Appender.SmtpAppender">
<!-- the level you want to see in the email IF ErrorHolder finds anything -->
<threshold value="INFO"/>
<bufferSize value="512" />
<lossy value="false" /> <!-- important! -->
<to value="[email protected]" />
<from value="[email protected]" />
<subject value="ERROR: subject" />
<smtpHost value="smtpserver" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline%date [%thread] %-5level %logger [%property{NDC}] - %message%newline%newline%newline" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="ErrorHolder" />
<appender-ref ref="Email" />
</root>
At the end of the app run this to disable the SmtpAppender
if the ErrorHolder
appender is empty:
// trigger loggers if errors occurred:
var memoryAppender = ((Hierarchy)LogManager.GetRepository())
.Root.Appenders.OfType<MemoryAppender>().FirstOrDefault();
if (memoryAppender != null && memoryAppender.GetEvents().Length == 0)
{
// there was no error so don't email anything
var smtpAppender = ((Hierarchy)LogManager.GetRepository())
.Root.Appenders.OfType<SmtpAppender>().FirstOrDefault();
if (smtpAppender != null)
{
smtpAppender.Threshold = Level.Off;
smtpAppender.ActivateOptions();
}
}