Hi, folks!
Today I am going to show you how to set logging of your project with minimum effort using NLog. NLog is a simple to use logging platform with good documentation, tutorials and examples and also available source code. You can install package using NuGet selecting NLog.Config, which will also install it’s dependencies (NLog and NLog.Schema). Installation adds NLog.dll to our project refrences, NLog.config for configuration and NLog.xsd (which won’t be needed in our case).
Initial configuration is simple and allows basic internal logging. But our goal is to set new log file each day with date in it’s name and email notifications in case of warnings and (fatal) errors.
<variable name="logFilePath" value="Logs\NLog.${shortdate}.log" />
Inside of variable tag we declared log file path with short date in it’s name. With date in it’s name new log file will be created every day. After that we have to create a file target and mail target:
<targets>
<target name="logfile"
xsi:type="File"
fileName="${logFilePath}"
layout="${longdate} LEVEL=${level:upperCase=true}: ${message}${newline} (${stacktrace}) ${exception:format=tostring}"
keepFileOpen="true" />
<target name="mail"
xsi:type="Mail"
smtpServer="my.smtp.server.com"
smtpPort="port"
smtpUserName="user.name"
smtpPassword="password"
subject="${machinename} - My subject string (${shortdate:format=dd. MM. yyyy})"
from="address.to.send.from@mail.com"
to="address.to.send.to@mail.com"
layout="${longdate} LEVEL=${uppercase:${level}}, LOCATION=${callsite:className=true:includeSourcePath=true:methodName=true},
MESSAGE=${message}${newline} EXCEPTION=${exception:format=tostring,StackTrace}${newline}" />
</targets>
Now we have two targets. First named “logfile” will add new entries to our log. Eeach entry will consist from long date, level and message. After message there will be new line with stacktrace and exception message. Second named “mail” will send email to address.to.send.to@mail.com. Entry will be quite similar as previous with added location (class name and method name). But we have a problem – each log entry will be sent separately! If we want to send all entries in one single email, we have to wrap our “mail” target with target of type BufferingWrapper:
<target name="mailbuffer" xsi:type="BufferingWrapper" slidingTimeout="false" bufferSize="100" flushTimeout="-1">
<target name="mail"
xsi:type="Mail"
smtpServer="my.smtp.server.com"
smtpPort="port"
smtpUserName="user.name"
smtpPassword="password"
subject="${machinename} - My subject string (${shortdate:format=dd. MM. yyyy})"
from="address.to.send.from@mail.com"
to="address.to.send.to@mail.com"
layout="${longdate} LEVEL=${uppercase:${level}}, LOCATION=${callsite:className=true:includeSourcePath=true:methodName=true},
MESSAGE=${message}${newline} EXCEPTION=${exception:format=tostring,StackTrace}${newline}" />
</target>
Problem solved. 🙂 Now we will get all entries inside of a single email. After that we have to set rules, which will tell NLog which level of entries must be written to which target.
<rules>
<logger name="*" minlevel="Info" writeTo="logfile" />
<logger name="*" minlevel="Warn" writeTo="mailbuffer"/>
</rules>
With those rules two rules we told NLog to log to file everything with level equal or higher to Info and to send an email of everything with level equal or higher to warning. Out logger is now configured. After that we have to add namespace to each class we want to log (using NLog;). We also have to initialize our logger. After that we can start to create logs:
class Program
{
private static Logger logger = LogManager.GetCurrentClassLogger();
static void Main(string[] args)
{
logger.Info("This is the first line of Main method.");
try
{
throw new Exception("This is one badass exception. :)");
}
catch (Exception ex)
{
logger.Error(ex, "It seems the exception happened. :(");
}
logger.Warn("This is your last warning!");
logger.Fatal("And this is fatal error...");
}
}
Here you can download config file and short code snippet: NLog config and short code snippet. Before using you have to configure SMTP parameters (you can find all possible parameters in documentation or you can check this example (both on GitHub)).