Logging in MVC Part 4 – Log4Net

This is part 4 of the MVC Logging series. Other articles in the series are:

Introduction

In this article we will quickly add Log4Net into the website so that later on we can decide whether to use Log4Net or NLog to log our custom messages.

Log4Net is a very widely used logger and it is quite likely that you have 3rd party dependencies in your website that already use Log4Net so it can be a good idea to track any messages that it logs.

Log4Net

The steps we need to follow are:

1. Download Log4Net
2. Add a reference to Log4Net
3. Add a table in our database to store the Log4Net logs
4. Modify the web.config file for Log4Net
5. Implement a Log4NetLogger that implements our ILogger interface.

Setting up the database

Run the following script to create the table that Log4Net will log message to:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[Log4Net_Error](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[Date] [datetime] NOT NULL,
	[Thread] [varchar](255) NOT NULL,
	[Level] [varchar](50) NOT NULL,
	[Logger] [varchar](255) NOT NULL,
	[Message] [varchar](4000) NOT NULL,
	[Exception] [varchar](2000) NULL
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

Web.config configuration

Add the following to the top of your web.config file:

<configuration>
  <configSections>
   ...
  <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  ...
  </configSections>
</configuration>

Add the following underneath the configuration element in your web.config file:

<log4net>
    <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
      <bufferSize value="100" />
      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <connectionString value="data source=[Machine]/[Instance];Initial Catalog=[DatabaseName];Integrated Security=True" />
      <commandText value="INSERT INTO Log4Net_Error ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />
      <parameter>
        <parameterName value="@log_date" />
        <dbType value="DateTime" />
        <layout type="log4net.Layout.RawTimeStampLayout" />
      </parameter>
      <parameter>
        <parameterName value="@thread" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%thread" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@log_level" />
        <dbType value="String" />
        <size value="50" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%level" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@logger" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%logger" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@message" />
        <dbType value="String" />
        <size value="4000" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%message" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@exception" />
        <dbType value="String" />
        <size value="2000" />
        <layout type="log4net.Layout.ExceptionLayout" />
      </parameter>
    </appender>

    <!-- Set root logger level to DEBUG and its only appender to A1 -->
    <root>
      <level value="DEBUG" />
      <appender-ref ref="AdoNetAppender" />
    </root>
  </log4net>

Implement a Log4NetLogger

Now let’s create a logger class for Log4Net that implements our ILogger interface (discussed in part 3).1. Create a new folder underneath the Services folder. Our folder structure will be like this:
Services -> Logging -> Log4Net

2. Create a new class file in the new folder and name it ‘Log4NetLogger.cs’.

3. Add the following code to the class:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using log4net;

namespace MvcLoggingDemo.Services.Logging.Log4Net
{
 public class Log4NetLogger : ILogger
 {

 private ILog _logger;

 public Log4NetLogger()
 {
 _logger = LogManager.GetLogger(this.GetType());
 }

 public void Info(string message)
 {
 _logger.Info(message);
 }

 public void Warn(string message)
 {
 _logger.Warn(message);
 }

 public void Debug(string message)
 {
 _logger.Debug(message);
 }

 public void Error(string message)
 {
 _logger.Error(message);
 }

 public void Error(Exception x)
 {
 Error(LogUtility.BuildExceptionMessage(x));
 }

 public void Error(string message, Exception x)
 {
 _logger.Error(message, x);
 }

 public void Fatal(string message)
 {
 _logger.Fatal(message);
 }

 public void Fatal(Exception x)
 {
 Fatal(LogUtility.BuildExceptionMessage(x));
 }
 }
}

You will notice that the code above is almost identical to the one we created for NLog. The only difference is the line in the constructor that instantiates the Log4Net logger.

Testing the Log4Net logger

The last step is to write some code that uses our new debugger. Update the Index method of our Activity controller like this:
(You will also need to add a refernce to the namespace, “MvcLoggingDemo.Services.Logging.Log4Net” at the top of your file)

public ActionResult Index()
 {
 IEnumerable list = activityRepository.GetAll();

 NLogLogger logger = new NLogLogger();
 logger.Info("Test message for NLog");

 Log4NetLogger logger2 = new Log4NetLogger();
 logger2.Info("Test message for Log4Net");

 try
 {
 throw new Exception("A test exception");
 }
 catch(Exception ex)
 {
 Console.WriteLine("ERROR - An error has occurred");
 }

 return View(list);
 }

Now go to the Index page for Activities and inspect the Log4Net_Error table to ensure that the message has been logged.

Conclusion

We now have Elmah, NLog, Log4Net and Health monitoring setup and working on our website. The next few articles will focus on building a log reporting viewer so that we can tie all of these things together so that we can see a consolidated and consistent view of everything that is getting logged on our website.

Download

The source code for part 4 is on the Downloads tab of the associate CodePlex website

Tagged with: , , , ,
Posted in ASP.NET MVC
4 comments on “Logging in MVC Part 4 – Log4Net
  1. Daudi says:

    Hi Darren,
    Your logging series was most helpful. Thanks and keep up the good work.

    Rgs
    Daudi

  2. Eric Smith says:

    I couldn’t get this to work until I added this.
    log4net.Config.XmlConfigurator.Configure();

    Maybe I missed it somewhere in your tutorial.

  3. kevin says:

    good work. thanks

  4. dave says:

    I also couldn’t get this to work until I put
    log4net.Config.XmlConfigurator.Configure(); into the Global.asax ?!!?

    (nb asp.net4, mvc3 and log4net1.2.10)

Leave a comment