Dynamics AX 2009 Logging (File based) using Log4Net

I was looking for logging Dynamics AX messages to files so that they can be further used by other monitoring applications to determine if the application is running as per expectations. This requires huge amount of file based logging to assure monitoring applications get sufficient details to draw different graphs explaining if the processes are taking normal time, if the data load is normal and other analysis.

Given the fact that there were too many logs to be written, I opted for Log4Net as it is fast as well as highly configurable logging API. Below is the excerpt from Apache’s site for Log4Net which explains it better.

Log4net is a tool to help the programmer output log statements to a variety of output targets. In case of problems with an application, it is helpful to enable logging so that the problem can be located. With log4net it is possible to enable logging at runtime without modifying the application binary. The log4net package is designed so that log statements can remain in shipped code without incurring a high performance cost. It follows that the speed of logging (or rather not logging) is crucial.

At the same time, log output can be so voluminous that it quickly becomes overwhelming. One of the distinctive features of log4net is the notion of hierarchical loggers. Using these loggers it is possible to selectively control which log statements are output at arbitrary granularity.

log4net is designed with two distinct goals in mind: speed and flexibility

I will not cover Log4Net configurations and uses in this article as there are lot of good tutorials available online. Log4Net comes with different types of appenders but this article will only stick to Rolling File Appender. For more information on different appenders check this

To integrate Log4Net with Dynamics AX 2009, below is what I did.

Create a new Project of type Class Library in Visual Studio

image

Set the Target Framework of your Project to .Net Framework 3.5, by right clicking the Project in Solution Explorer and clicking Properties. This is required for Dynamics AX to recognize the DLL when its reference is added.

image

Next step is to add the Log4Net references. This can be done either by downloading the binaries from here and adding the reference or by using nuget Package. I preferred to install Log4Net using nuget package. Open Package Manager Console and type Install-Package log4net and hit Enter.

image

 

After the above step is completed, we now have the Log4Net dll reference added to our project

image

 

The next step is to add the log4net.config file which is the actual configuration about how things should get logged. I won’t go into the details about what the configurations are as all this information is available in the link shared at the top of this article.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <log4net>
    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="C:\Logs\MyFirstLogger.log"/>
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="2" />
      <maximumFileSize value="1MB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
      </layout>
    </appender>
    <root>
      <level value="ALL" />
      <appender-ref ref="LogFileAppender" />
    </root>
  </log4net>
</configuration>

 

Set the Copy to Output Directory property of log4net.config file to “Copy always”. This is required to make sure the file gets copied in the bin folder when you compile the application.

image

Add a new Class file to your project, LogToFile.cs in my case and add the below code. This is the class which will be used to perform the actual logging operations from Dynamics AX.

Add an enum to the class to define the type of log that needs to be created

 

public enum LogType
{
    Debug,
    Info,
    Warn,
    Error,
    Fatal
}

 

Create an ICollection object to configure log4net using the configuration file we created as follows

private ICollection configure = XmlConfigurator.Configure(new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "\\log4net.config"));

 

Create an ILog object which will be used to log the messages using Log4Net

 

private readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

 

Create a new method named WriteLog which will be called from Dynamics AX to log the messages to file

 

		public void WriteLog(LogType logType, string message, Exception ex)
        {
            switch (logType)
            {
                case LogType.Debug:
                    log.Debug(message, ex);
                    break;
                case LogType.Info:
                    log.Info(message, ex);
                    break;
                case LogType.Warn:
                    log.Warn(message, ex);
                    break;
                case LogType.Error:
                    log.Error(message, ex);
                    break;
                case LogType.Fatal:
                    log.Fatal(message, ex);
                    break;
                default:
                    break;
            }

 

Below is the complete class code.

 

using log4net;
using log4net.Config;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace AX.Log4Net
{
    // Enum used to define the type of event that occured
    public enum LogType
    {
        Debug,
        Info,
        Warn,
        Error,
        Fatal
    }

    public class LogToFile
    {
        // Assures that the Log4Net picks up the log4net.config file created by us
        private ICollection configure = XmlConfigurator.Configure(new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "\\log4net.config"));
        private readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        
        public void WriteLog(LogType logType, string message)
        {
            this.WriteLog(logType, message, null);
        }

        public void WriteLog(LogType logType, string message, Exception ex)
        {
            switch (logType)
            {
                case LogType.Debug:
                    log.Debug(message, ex);
                    break;
                case LogType.Info:
                    log.Info(message, ex);
                    break;
                case LogType.Warn:
                    log.Warn(message, ex);
                    break;
                case LogType.Error:
                    log.Error(message, ex);
                    break;
                case LogType.Fatal:
                    log.Fatal(message, ex);
                    break;
                default:
                    break;
            }
        }
    }
}

 

The next step is to compile the project. After compiling the project we require the below files from the bin folder

  • AX.Log4Net.dll (The DLL for our Project)
  • log4net.config (The config file containing our appender details)
  • log4net.dll (The original Log4Net DLL reference added to our solution)

 

Depending on whether the process which needs to create the logs runs on client or server side, the above files need to be copied to Dynamics AX Client’s or Server’s bin folder.

Now we need to add our DLL’s reference in Dynamics AX. Under AOT right click References and hit Add Reference. Click Browse and select the AX.Log4Net.dll from Dynamics AX Client’s bin folder

SNAGHTML41dcdae

We will test the integration using a Dynamics AX Job, so lets go ahead and create a test job to check how this works. Note that you may require to restart AOS service after this change.

 

static void JobTestLog4Net(Args _args)
{
    AX.Log4Net.LogToFile logToFile = new AX.Log4Net.LogToFile();
    ;

    logToFile.WriteLog(AX.Log4Net.LogType::Info, "Info");
    logToFile.WriteLog(AX.Log4Net.LogType::Debug, "Debug");
    logToFile.WriteLog(AX.Log4Net.LogType::Error, "Error");
    logToFile.WriteLog(AX.Log4Net.LogType::Fatal, "Fatal");
    logToFile.WriteLog(AX.Log4Net.LogType::Warn, "Warning");
}

 

On running the Dynamics AX Job, we should find a file named MyFirstLogger.log under C:\Logs folder with similar to below contents

 

2015-01-30 17:06:28,670 [1] INFO  AX.Log4Net.LogToFile Info
2015-01-30 17:06:28,670 [1] DEBUG AX.Log4Net.LogToFile Debug
2015-01-30 17:06:28,670 [1] ERROR AX.Log4Net.LogToFile Error
2015-01-30 17:06:28,670 [1] FATAL AX.Log4Net.LogToFile Fatal
2015-01-30 17:06:28,685 [1] WARN  AX.Log4Net.LogToFile Warning

 

Log4Net is a very powerful utility for any type of logging and making our life easier. Do comment with your questions or recommendations.

Add a Comment