Mahmoud ElMansy: knowledge meant to be free

Implementing Custom Log4Net using AdoNetAppender and simple Wrapper with Asp.Net Mvc

Assalamo Alikom
This post comes after a quite long pause, but I found this very useful article which encouraged me to write in this topic.

In this post i will Illustrate how to make Wrapper class(mimic structure, but simply hide complexity/advanced/unwanted functionality) to manage Log4net Classes in an manageable and easy way .

First Log4Net for whom don’t know it as described on their homepage

The Apache log4net library is a tool to help the programmer output log statements to a variety of output targets.

I want talk more about Log4Net and you can review full Documentation Here

Now To Code 🙂

I will build simple Mvc Web Application to illustrate how to make Log4net Up and running and make easy Wrapper
to implement and catch all logs.

Enough talking open your visual studio 2013 IDE.

1) Create Mvc Project Called Log4Net_MVC.

  • And add new Project of type Class library name it Log4NetWrapper.
  • Download load Log4net DLL from Here
  • Add Folder name it Dlls and but the log4net.dll,log4net.xml files and add reference to them on class library project
  • Run the “Log.sql” Script to your database

2) In the Mvc Project

  • Add reference to Log4NetWrapper project.
  • Configure the Log4Net.config file to meet your requirement and here is some example of how to do this.

I configured my own File and here is some keys to understand the file .

I added two Appender “Ways to write logs”

   <appender name="DebugAppender" type="log4net.Appender.DebugAppender"> <!-- To write on the OutPut Window for Visual Studio To Debug Errors  -->
   <appender name="AdoNetAppender_SqlServer" type="log4net.Appender.AdoNetAppender">
<!-- To write logs into DataBase -->

I added two Custom Parameters i need to write “[ProjectID],[UserID]”
and to do that i added them to ‘commandText’

   <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception],[ProjectID],[UserID]) VALUES (@log_date, @thread, @log_level, @logger, @message,@exception,@ProjectID,@UserID)"/>

And added them to the ‘Parameter’ collection .

 <parameter>
        <parameterName value="@ProjectID"/>
        <dbType value="String" />
        <size value="20" />
        <layout type="log4net.Layout.PatternLayout" >
          <conversionPattern value="%property{ProjectID}" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@UserID"/>
        <dbType value="String" />
        <size value="20" />
        <layout type="log4net.Layout.PatternLayout" >
          <conversionPattern value="%property{UserID}" />
        </layout>
      </parameter>

Now i will refer to two important Keys

1- bufferSize this key means log4net store logs in queue and this the number where reache it will start flush the queue and write them into your database this very good for performance Choose wisely .

 <!-- number of logs to immediate write --><bufferSize value="1" />

2- useTransactions this key true/false

<useTransactions value="false" />

3) Add the Log4Net.config file to the root of your Mvc project and modify the Log4netConnectionString to refer to your database.

4) Add new class name it CommonMethods.

5) Add this global function to the class “WriteLog“.

public void WriteLog(object pMessage, Gehbeez.BaseDataLayer.Logging.LogType pLogType)
{
Gehbeez.BaseDataLayer.Logging.Logger.Instance.WriteLog(pMessage, pLogType,
new Gehbeez.BaseDataLayer.Logging.loggingParameter()
{ UserID = CommonMethods.Instance.CurrentUserID.HasValue ? CommonMethods.Instance.CurrentUserID.Value.ToString() : "0", ProjectID = "12" });
}

Here it is important to say that the loggingParameter is a class holds your custom parameter

Note That Parameter name must match your custom configuration parameters and i added this method to enable Log4Net to catch their values

 private void PushLoggingProperties(object loggingParameter)
        {
            if (loggingParameter != null)
            {
                Type attrType = loggingParameter.GetType();
                System.Reflection.PropertyInfo[] properties = attrType.GetProperties(
                               System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
                for (int i = 0; i < properties.Length; i++)
                {
                    object value = properties[i].GetValue(loggingParameter, null);
                    if (value != null)
                        log4net.ThreadContext.Properties[properties[i].Name]=value.ToString();
                }
            }
        }

6) Add these two additional Propertes

public static CommonMethods Instance
{
get
{
return new CommonMethods();
}
}

public int? CurrentUserID
{
get
{
try
{
return int.Parse(HttpContext.Current.User.Identity.Name);
}
catch { return null; }
}
}

7) Add now new Controller name it HomeController.

8) Past this code to Ilestrate how it will work.

public ActionResult Index()
{
// Normal Log
Log4Net_MVC.App_Code.CommonMethods.Instance.WriteLog("Execute Home&gt;&gt;&gt;&gt;Index", Gehbeez.BaseDataLayer.Logging.LogType.EnterMethod);

try {
//Sample
throw new Exception("Custom Exception");
}
catch (Exception ex) {/* Catch Error */ Log4Net_MVC.App_Code.CommonMethods.Instance.WriteLog(ex, Gehbeez.BaseDataLayer.Logging.LogType.Error); }

return View();
}

 

Now the result will be like this

Log Table

Log Table

Download full working sample Log4Net_MVC