How to use NLog and Common.Logging with Nhibernate

In this article we will show how you can add logging to an application by using NLog along with Common.Logging. We will also explain how to configure the logging for Nhibernate.

Introduction

  • NLog is a logging platform. This will handle the actual logging.
  • Common.Logging is an interface to the logging platform. An abstraction so that if in the future you need to switch the logging platform, it will be as easy as changing the configuration.
  • Nhibernate is an object-relational mapper. You can disregard this part if you don’t use it.

Install the frameworks

First step is to install the necessary assemblies. You will need:

  • NLog
  • NLog Configuration
  • NLog Schema for Intellisense(TM)
  • Common.Logging
  • Common.Logging.NLog20 (if using NLog version 2)
  • Nhibernate.Logging (if using Nhibernate)

You can do this through NuGet or by downloading from their respective websites.

NuGet NLog
NuGet NLog
NuGet Common.Logging
NuGet Common.Logging
NuGet Nhibernate.Logging
NuGet Nhibernate.Logging

Configure NLog

You should have an NLog.config file in the root of your project.

By default it comes with some commented lines. You can uncomment them to have basic logging or customize them to your needs.

Here is another example:

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <targets>
  <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
   layout="${longdate} ${logger} ${uppercase:${level}} ${message} ${exception:format=ToString,StackTrace,method:maxInnerExceptionLevel=5:innerFormat=ToString}" />
 </targets>
 <rules>
  <logger name="NHibernate.SQL" minlevel="Debug" writeTo="f" final="true" />
  <logger name="NHibernate.*" minlevel="Warn" writeTo="f" final="true" />
  <logger name="*" minlevel="Trace" writeTo="f" />
 </rules>
</nlog>

First we specify the targets. In this case we will log to a file and use the date as the filename.

The layout specifies what will be saved:

  • longdate: the full date.
  • logger: the logger name.
  • level: the log level (e.g. info, debug, error)
  • message: the logged message.
  • exception: exception information. We are specifying a specific format and also writing the stack trace and up to 5 inner exceptions.

Then we specify the routing rules. We have two rules for Nhibernate (or else you will flood your log files) and then a general rule for all other sources.

You can check the documentation about configuring NLog for more information.

Configure Common.Logging

You can configure Common.Logging in the App.config file, where information about the assemblies should have been automatically added.

You need to add a section for Common.Logging and specify the factory adapter. In this case, to use in conjunction with NLog:

<configuration>
 <configSections>
  <sectionGroup name="common">
   <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
  </sectionGroup>
 </configSections>
 <common>
  <logging>
   <factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog20">
    <arg key="configType" value="FILE" />
    <arg key="configFile" value="~/NLog.config" />
   </factoryAdapter>
  </logging>
 </common>
 <runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
   <dependentAssembly>
    <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
   </dependentAssembly>
   <dependentAssembly>
    <assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
   </dependentAssembly>
  </assemblyBinding>
 </runtime>
 <appSettings>
  <add key="nhibernate-logger" value="NHibernate.Logging.CommonLogging.CommonLoggingLoggerFactory, NHibernate.Logging.CommonLogging" />
 </appSettings>
</configuration>

Here we also configure the logging for Nhibernate.

How to log

Now comes the fun part - the actual logging!

In my case, I add a ILog member to my base view model:

readonly ILog _log;

Then I initialize it in the constructor of the view model:

_log = LogManager.GetLogger(GetType());

And I call it when I need to log something:

_log.Info("Test!");

This is the output in the log file:

2014-03-04 15:40:11.6753 WpfApplication1.MainWindowViewModel INFO Test! 

Log viewers

Now that you have all those log files, you probably want a better way of viewing them.

Here are some alternatives:

Log Format for Legit Log Viewer

<LogFormat xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns="http://www.legitlog.com/LogFormatSchema.xsd"
       FormatName="NLog">
  <Description>
    ${longdate} ${logger} ${uppercase:${level}} ${message} ${exception}
  </Description>
  <LogLine>
  <Fields>
        <LogFieldFormat Name="DateTime" FieldType="DateTime" Delimiter=" " Format="yyyy-MM-dd HH:mm:ss.ffff" />
        <LogFieldFormat Name="Logger" FieldType="String" Delimiter=" " />
        <LogFieldFormat Name="Level" FieldType="String" Delimiter=" " FilterColumn="true" HighlightRows="true" />
        <LogFieldFormat Name="Message" FieldType="String" Delimiter="&#xD;&#xA;" Multiline="true" />
  </Fields>
  </LogLine>
</LogFormat>
Nuno Freitas
Posted by Nuno Freitas on April 28, 2014

Related articles