NLOG New Utility For Smart Logging

NLog is a free logging platform for .NET, Silverlight, and Windows Phone with rich log routing and management capabilities. It makes it easy to produce and manage high-quality logs for your applications regardless of their size or complexity. When you don't want to care about the archiving, log formats then NLog is your friend. Using just a few configuration settings will enable everything for you. So let's get started.
 
First, download the appropriate version of Nlog that you'll be using in your application. Now when you have the desired library of Nlog just add the reference to your project. The next thing you need to do is put some configuration lines in the config file.
 
Register the NLog section in config:
  1. <configuration>  
  2.   <configSections>  
  3.     <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>  
  4. </configSections> 
Note: keep in mind you're putting the config sections tag at the top of the Configuration file otherwise you'll get an exception "Can not have more than one config section in the configuration" something like that.
 
Next you need to specify the Nlog section to be defined. The following is the sample code configuration of Nlog required to enable the logging in your application.
  1. <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwExceptions="true" internalLogFile="c:\temp\nLog_internal_log_file.txt" internalLogLevel="Trace" internalLogToConsole="true">  
  2.      <targets async="true">  
  3.           <target name="file" xsi:type="File" keepFileOpen="false" fileName="C:\\Temp\\Test_Log.MyApplication.${shortdate}.txt" layout="${newline}${newline}${level}: ${message} ${exception:format=Message,StackTrace}" archiveFileName="C:\\Temp\\archives\Log.FaultDetectionSitePoller.{#####}.txt" lineEnding="Default" archiveAboveSize="1024000" archiveNumbering="Sequence" concurrentWrites="true" />  
  4.           <target xsi:type="Database" name="database">  
  5.                <connectionString>  
  6.                     data source=LABPC02;initial catalog=SampleDatabase;Integrated Security=SSPI;  
  7.                </connectionString>  
  8.                <commandText>  
  9.                     INSERT INTO Diagnostics  
  10.                     (Severity  
  11.                     ,Message  
  12.                     ,StackTrace  
  13.                     ,User  
  14.                     ,MachineName  
  15.                     )  
  16.                     VALUES ( @severity  
  17.                     , @message  
  18.                     , @stacktrace  
  19.                     , @User  
  20.                     , @machinename  
  21.                     )  
  22.                </commandText>  
  23.                <parameter name="@severity" layout="${level}" />  
  24.                <parameter name="@message" layout="${message}" />  
  25.                <parameter name="@machinename" layout="${machinename}" />  
  26.                <parameter name="@User" layout="${windows-identity:domain=true}" />  
  27.                <parameter name="@stacktrace" layout="${stacktrace}" />  
  28.           </target>  
  29.      </targets>  
  30.      <rules>  
  31.           <logger name="*" writeTo="file" />  
  32.           <logger name="*" minLevel="OFF" appendTo="database" />  
  33.      </rules>  
  34. </nlog> 
In this section, we have a couple of things that I need to explain.
 
InternalLogFile
 
This is the file that Nlog will use for its own logging. It'll help you troubleshoot any issue with the NLog configuration with your project. It's optional and not required if you don't want to log the status of Nlog's internal stuff.
 
InternalLogToConsole
 
You can turn it on/off if your application can run as a console application.
 
Targets
 
This is the section where you define the targets i.e. your logging will be done in file or database etc. The attribute async='true' will define the behavior of Nlog to be async when writing logs. So you don't need to consider the cost of logging statements if you're using the async write behavior. Which is a great feature that I liked most cause I've seen the application consuming enough time/space for logging statements. In the given sample configuration we have file and database logging enabled in the targets table.
 
Renderlayouts
 
Whatever is written under the target tag in the Curley braces is called render layouts. Whatever I used are the internally defined templates by Nlog. You can also create your own templates. These templates are known as RenderLayouts. So Nlog is already providing a very good list of RenderLayouts; check them out here.
 
That's pretty much what is required to be done in the configuration area. Now you need to write a wrapper class that you'll be using in your project.
 
Here's the complete code for the wrapper:
  1. using System;  
  2. using NLog;  
  3.   
  4. namespace MyLogger {  
  5.     public static class Logger {  
  6.         private static readonly NLog.Logger _logger; //NLog logger  
  7.         private  
  8.         const string _DEFAULTLOGGER = "CustomLogger";  
  9.   
  10.         static Logger() {  
  11.             _logger = LogManager.GetLogger(_DEFAULTLOGGER) ? ? LogManager.GetCurrentClassLogger();  
  12.         }  
  13.  
  14.         # region Public Methods  
  15.         /// <summary>  
  16.         /// This method writes the Debug information to trace file  
  17.         /// </summary>  
  18.         /// <param name="message">The message.</param>  
  19.         public static void Debug(String message) {  
  20.             if (!_logger.IsDebugEnabled) return;  
  21.             _logger.Debug(message);  
  22.         }  
  23.   
  24.         /// <summary>  
  25.         /// This method writes the Information to trace file  
  26.         /// </summary>  
  27.         /// <param name="message">The message.</param>  
  28.         public static void Info(String message) {  
  29.             if (!_logger.IsInfoEnabled) return;  
  30.             _logger.Info(message);  
  31.         }  
  32.   
  33.         /// <summary>  
  34.         /// This method writes the Warning information to trace file  
  35.         /// </summary>  
  36.         /// <param name="message">The message.</param>  
  37.         public static void Warn(String message) {  
  38.             if (!_logger.IsWarnEnabled) return;  
  39.             _logger.Warn(message);  
  40.         }  
  41.   
  42.         /// <summary>  
  43.         /// This method writes the Error Information to trace file  
  44.         /// </summary>  
  45.         /// <param name="error">The error.</param>  
  46.         /// <param name="exception">The exception.</param>  
  47.         public static void Error(String error, Exception exception = null) {  
  48.             if (!_logger.IsErrorEnabled) return;  
  49.             _logger.ErrorException(error, exception);  
  50.         }  
  51.   
  52.         /// <summary>  
  53.         /// This method writes the Fatal exception information to trace target  
  54.         /// </summary>  
  55.         /// <param name="message">The message.</param>  
  56.         public static void Fatal(String message) {  
  57.             if (!_logger.IsFatalEnabled) return;  
  58.             _logger.Warn(message);  
  59.         }  
  60.   
  61.         /// <summary>  
  62.         /// This method writes the trace information to trace target  
  63.         /// </summary>  
  64.         /// <param name="message">The message.</param>  
  65.         public static void Trace(String message) {  
  66.             if (!_logger.IsTraceEnabled) return;  
  67.             _logger.Trace(message);  
  68.         }  
  69.  
  70.         # endregion  
  71.     }  

So the usage of this wrapper should be very simple as you will only need to write lines in the middle of your code.
  1. Logger.Debug("Time elapsed: " + timeElapsed); 
And you're done with setting up the new generation logger with your application. If you need to turn off the logging for any target then you can use minLevel="OFF" for that target.
 
For example:
 
<logger name="*" minLevel="OFF" appendTo="database"/>