MVC Error Logging Using Log4Net Learning Note 4

  • 2021-08-21 20:12:03
  • OfStack

In the process of Web application running, we will inevitably encounter abnormal program running. At this time, we should record the abnormal information, so that developers and maintenance personnel can restore and repair the abnormal reasons. There are also many logging components in ASP. NET platform, such as Log4Net, CommonLogging, etc. We choose Log4Net for exception logging.

1. Catch exceptions

A global exception handling filter, HandleErrorAttribute, is provided in ASP. NET MVC, through which exception information can be captured.

We create a new type Log4ExceptionAttribute under the Models folder, inherit the HandleErrorAttribute class, and override the OnException method to catch exception data:


using System.Web.Mvc;

namespace PMS.WebApp.Models
{
  public class Log4ExceptionAttribute:HandleErrorAttribute
  {
    /// <summary>
    ///  Rewrite OnException Method to catch abnormal data 
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnException(ExceptionContext filterContext)
    {
      base.OnException(filterContext);
      // Capture the current exception data 
      var ex = filterContext.Exception;
    }
  }
}

After creating a new filter, we also need to complete the registration of our own exception handling filter in the RegisterGlobalFilters method called in the Global file.


using System.Web.Mvc;
using PMS.WebApp.Models;

namespace PMS.WebApp
{
  public class FilterConfig
  {
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
      //filters.Add(new HandleErrorAttribute());
      filters.Add(new Log4ExceptionAttribute());
    }
  }
}

2. Considering the possible problems when multiple users operate concurrently, we need to create a new queue to temporarily store exception information, and at the same time open a thread to deal with exception information in the queue.

In the Log4ExceptionAttribute class, a new static exception type queue is created. After an exception occurs, the program automatically triggers the OnException method, which jumps to the error page after entering the current exception information into the queue.


using System;
using System.Collections.Generic;
using System.Web.Mvc;

namespace PMS.WebApp.Models
{
  public class Log4ExceptionAttribute:HandleErrorAttribute
  {
    public static Queue<Exception> Exceptions=new Queue<Exception>();
    /// <summary>
    ///  Rewrite OnException Method to catch abnormal data 
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnException(ExceptionContext filterContext)
    {
      base.OnException(filterContext);
      // Capture the current exception data 
      var ex = filterContext.Exception;
      // Queuing abnormal data 
      Exceptions.Enqueue(ex);
      // Jump to error page 
      filterContext.HttpContext.Response.Redirect("/Error.html");
    }
  }
}

The configuration of Log4Net is done in the application configuration file, where we first configure Log4Net. The node position to be configured in Log4Net is exactly the same as that in SpringNet. First, child nodes need to be added in configSessions, and then log4net nodes need to be added in configuration nodes to complete specific configuration.


<configuration>
 <configSections>
  <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
  
  <!-- ↓ Log4Net Configuration  ↓  -->
  <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  <!-- ↑ Log4Net Configuration -->
  
  <!-- ↓ Spring.Net Configuration  ↓  -->
  <sectionGroup name="spring">
   <section name="context" type="Spring.Context.Support.MvcContextHandler, Spring.Web.Mvc4"/>
  </sectionGroup>
  <!-- ↑ Spring.Net Configuration -->
  
 </configSections>
 
 <!-- ↓ Spring.Net Configuration  ↓  -->
 <spring>
  <context>
   <resource uri="file://~/Config/controllers.xml"/>
   <resource uri="file://~/Config/services.xml"/>
  </context>
 </spring>
 <!-- ↑ Spring.Net Configuration -->
 
 <!-- ↓ Log4Net Configuration  ↓  -->
 <log4net>
  <!-- OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL -->
  <!-- Set root logger level to ERROR and its appenders -->
  <root>
   <level value="ALL"/>
   <appender-ref ref="SysAppender"/>
  </root>

  <!-- Print only messages of level DEBUG or above in the packages -->
  <logger name="WebLogger">
   <level value="DEBUG"/>
  </logger>

  <appender name="SysAppender" type="log4net.Appender.RollingFileAppender,log4net" >
   <param name="File" value="App_Data/" />
   <param name="AppendToFile" value="true" />
   <param name="RollingStyle" value="Date" />
   <param name="DatePattern" value="&quot;Logs_&quot;yyyyMMdd&quot;.txt&quot;" />
   <param name="StaticLogFileName" value="false" />
   <layout type="log4net.Layout.PatternLayout,log4net">
    <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
    <param name="Header" value="&#13;&#10;----------------------header--------------------------&#13;&#10;" />
    <param name="Footer" value="&#13;&#10;----------------------footer--------------------------&#13;&#10;" />
   </layout>
  </appender>
  <appender name="consoleApp" type="log4net.Appender.ConsoleAppender,log4net">
   <layout type="log4net.Layout.PatternLayout,log4net">
    <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
   </layout>
  </appender>
 </log4net>
 <!-- ↑ Log4Net Configuration -->
 ...
</configuration>

In the configuration file, you can configure the log record information, format, file name, etc. The following is a detailed explanation of the configuration information


<?xml version="1.0"?>
<configuration>
 <configSections>
  <section name="log4net" 
       type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
 </configSections>
 <!-- Site Log Configuration Section -->
 <log4net>
  <root>
   <!-- Control level, from low to high : ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
   <!-- For example, the definition level is INFO , then INFO Level down, such as DEBUG The log will not be recorded -->
   <!-- If there is no definition LEVEL The default is the value of DEBUG-->
   <level value="ERROR"/>
   <appender-ref ref="RollingFileAppender"/>
  </root>
  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
   <!-- Beginning of log file name -->
   <file value="c:\Log\TestLog4net.TXT"/>
   <!-- Minimum locking when multithreading -->
   <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
   <!-- The format of the date is changed every day 1 File record, if not set, only record forever 1 The log of days needs to be set -->
   <datePattern value="(yyyyMMdd)"/>
   <!-- Append to file , Default to true Usually, you don't need to set -->
   <appendToFile value="true"/>
   <!-- The transformation is in the form of a date, in which case only one day 1 Log -->
   <!-- At this time MaxSizeRollBackups And maximumFileSize Node setting of is meaningless -->
   <!--<rollingStyle value="Date"/>-->
   <!-- The transformation is in the form of log size -->
   <!-- In this case MaxSizeRollBackups And maximumFileSize The node setting of makes sense -->
   <RollingStyle value="Size"/>
   <!-- The number of log files recorded every day, which is the same as maximumFileSize Combined use -->
   <MaxSizeRollBackups value="10"/>
   <!-- Maximum size per log file -->
   <!-- Available units :KB|MB|GB-->
   <!-- Do not use decimals , Otherwise it will 1 Write directly to the current log -->
   <maximumFileSize value="2MB"/>
   <!-- Log format -->
   <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%t]%-5p %c - %m%n"/>
   </layout>
  </appender>
 </log4net>
</configuration>

Open a thread in the Application_Start method in the Global file to write error messages from the queue to the log file.


using System.Linq;
using System.Threading;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using log4net;
using PMS.WebApp.Models;
using Spring.Web.Mvc;

namespace PMS.WebApp
{
  //  Attention :  About enabling  IIS6  Or  IIS7  Description of the classic pattern, 
  //  Please visit  http://go.microsoft.com/?LinkId=9394801

  public class MvcApplication : SpringMvcApplication//HttpApplication
  {
    protected void Application_Start()
    {
      log4net.Config.XmlConfigurator.Configure();// Read Log4Net Configuration information 
      AreaRegistration.RegisterAllAreas();

      WebApiConfig.Register(GlobalConfiguration.Configuration);
      FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
      RouteConfig.RegisterRoutes(RouteTable.Routes);
      BundleConfig.RegisterBundles(BundleTable.Bundles);

      // Open 1 Threads , Scan exception information queue .
      var filePath = Server.MapPath("/Log/");
      ThreadPool.QueueUserWorkItem((a) =>
      {
        while (true)
        {
          // Determine whether there is data in the queue 
          if (Log4ExceptionAttribute.Exceptions.Any())
          {
            // Out of the team 1 Exception message 
            var ex = Log4ExceptionAttribute.Exceptions.Dequeue();
            // If the exception information is not empty 
            if (ex == null) continue;
            // Write exception information to the log file 
            var logger = LogManager.GetLogger("errorMsg");
            logger.Error(ex.ToString());
          }
          else
          {
            // If the exception information queue is empty, the thread will rest 3 Seconds 
            Thread.Sleep(3000);
          }
        }
      }, filePath);
    }
  }
}

Configuration of error log completed successfully.


Related articles: