On a project I have been working on I was having a terrible time getting errors from the client. There were a plethora of database errors that I could not get to replicate on my local machine. Simple features like adding an object to the database or editing that object to the database would error. What is worse is that the client would not properly transcribe the error message for my debugging purposes.
To alleviate this pain I used log4net to send all errors to an email address. This way any errors that occur within the system can be sent directly to me, without user interaction, so I might investigate without the need for a middleman. The configuration was quite simple.
Within app.config:
<appender name="smtpAppender" type="log4net.Appender.SmtpAppender">
<to value="[To address]" />
<from value="[From address]" />
<subject value="Error" />
<authentication value="basic" />
<smtpHost value="[SMTP server]" />
<username value="[SMTP username]" />
<password value="[SMTP password]" />
<port value="[SMTP port]" />
<bufferSize value="10" />
<lossy value="true" />
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="ERROR"/>
</evaluator>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%newline%date [%thread] %-5level %logger [%property{NDC}] - %message%newline%newline%newline" />
</layout>
</appender>
This creates an appender that will send an email to the desired address with the proper smtp settings. Once the appender is created you need to create a logger that uses the appender.
<logger name="error-logger" additivity="false">
<level value="ERROR" />
<appender-ref ref="smtpAppender" />
</logger>
Then whenever you want to send an error via email you just log the error as an error using the error-logger logger. This will send an email.
Personally I like giving the option to send in case the user knows what went wrong to save on spam but it isn’t a requirement. This set up worked nicely for me.
My favorite logging library log4net work not only on desktop and web applications but can be used on mobile devices with the compact framework.
Granted not all of the Appenders make sense within the compact framework. Since mobile devices have neither a system log nor a console it doesn’t make much sense to have these appenders. For a complete list of supported frameworks and appenders see here.
Applications written in the compact framework don’t have app.config files. This presents an issue when attempting to create an ILog. Here is my work around.
First create an XML that will be copied to source on deployment. Here is an example:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<log4net debug="false">
<appender name="logger" type="log4net.Appender.RollingFileAppender">
<file value="\SD Card\Assessment\DamageAssessmentLog.txt" />
<appendToFile value="true" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="1048576" />
<rollingStyle value="Composite" />
<staticLogFileName value="false" />
<layout type="log4net.Layout.PatternLayout">
<header value="[Header] "/>
<footer value="[Footer] "/>
<conversionPattern value="%newline Date: %date ,Application: %a ,Logger: %logger ,Thread: [%thread] ,Level: %level %newline Message: %message%newline Exception: %exception%newline" />
</layout>
</appender>
<!-- Setup the root category, add the appenders and set the default level -->
<root>
<level value="DEBUG" />
<appender-ref ref="logger" />
</root>
</log4net>
</configuration>
This should all be familiar so far. Basically whatever was going to go into app.config will now be in this file.
Then within your application’s startup you need to explicitly point log4net to that configuration file.
Shared Sub Main()
Try
Dim logconfig = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase), "logging.config")
log4net.Config.XmlConfigurator.Configure(New FileInfo(logconfig))
Dim logger As ILog = log4net.LogManager.GetLogger("logger")
Using map As formMap = New formMap()
logger.Debug("Staring application")
map.ShowDialog()
logger.Debug("Application closed")
End Using
AssessmentConnector.Instance.CloseConnection()
Catch ex As Exception
MessageBox.Show(ex.ToString)
Finally
log4net.LogManager.Shutdown()
End Try
End Sub
Here you can see that I get the application’s executing path and append the xml file’s name. Then I call the log4net.Config.XmlConfigurator to initialize the logging service from the provided xml file.
Note: Due to limitations of the compact framework it is important that you call log4net.LogManager.Shutdown() to explicitly close your log files. Otherwise you’ll end up with a hanging process and open log files.