Starting in DotNetNuke 6.0 support was added for log4net, a first rate logging framework developed by the Apache Foundation.

So why log? Well any non trivial module can benefit from logging, it means you can easily debug an issue on a live site and see what is happening under the hood.
A liberal sprinkling of logging statements in your DotNetNuke module can save you a lot of time when you have some unexpected behaviour in your module.

DNN Logging 101

DNN have wrapped the standard log4net logging statements in a class called DnnLog which is part of the assembly DotNetNuke.Instrumentation.dll. So to get started with logging you need to add a reference to this dll in your code.

Within the logging framework we have different levels of log, this allows us to filter out some of the debug statements in a production DNN install and just log errors or fatal events to the log output for example. Starting at the lowest logging level going to the highest level we have

  • debug
  • info
  • warn
  • error
  • fatal

So if we have the logger set to record all debug level messages it will also log the higher log levels as well, if we however set the log to error level then only error and fatal would be record with the other lower levels ignored.

Within the DNN class DnnLog we have a method for each type of these logging events with various overloaded options.

DnnLog.Debug("Category ID:{0} is at depth:{1} of the category tree", c.CategoryID, depth);

So using this logging statement we can use string formatting to record the debug log message. We can also log exception using a different overloaded method. Using intellisense it is pretty easy to discovery the correct method to use.

Taking Control

So that is all there is to it, oh wait, where do the log messages appear and how do we control the level?

Within the root of the DNN site you will find the file DotNetNuke.log4net.config this is used to control the logging within the site. The default setting is to log to a file only error levels or above.
In a development environment it might be more productive to set the log level to debug so that we get all log statements. To do this we would simple edit the root level

  <level value="Error" />
  <appender-ref ref="RollingFile" />

To the new value of

  <level value="Debug" />
  <appender-ref ref="RollingFile" />

The RollingFile appender will log the output into a text file which can be found in this directory, \Portals\_default\Logs
A new log will be created each day, its important to remember that DNN won’t delete old log files so this could grow to be a large directory if left unchecked.

Bonus Tip

Something which can be useful when debugging and developing is to have the DNN log statements output in the standard Trace Output for the page.
Its a pretty simple thing to do, you would just need to add a new appender that uses the AspNetTraceAppender and then define the appender in the root element.

<?xml version="1.0" encoding="utf-8" ?> 
  <appender name="RollingFile" type="log4net.Appender.RollingFileAppender"> 
    <file value="Portals/_default/Logs/" /> 
    <datePattern value="yyyy.MM.dd'.log.resources'" /> 
    <rollingStyle value="Date" /> 
    <staticLogFileName value="false" /> 
    <appendToFile value="true" /> 
    <maximumFileSize value="10MB" /> 
    <maxSizeRollBackups value="5" /> 
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/> 
    <layout type="log4net.Layout.PatternLayout"> 
      <conversionPattern value="%date [%property{log4net:HostName}][Thread:%thread][%level] %logger - %message%newline" /> 
      <locationInfo value="true" /> 
  <appender name="AspNetTraceAppender" type="log4net.Appender.AspNetTraceAppender" > 
    <layout type="log4net.Layout.PatternLayout"> 
        <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" /> 
    <level value="DEBUG" /> 
    <appender-ref ref="RollingFile" /> 
    <appender-ref ref="AspNetTraceAppender" /> 

Then whenever you have Trace turned on the log statement

I hope you found this article useful and you give the DNN logging framework a try in your next module.