ASP.NET MVC中解决日志并发处理log4net

本章主要内容是将异常信息写到队列中,然后通过线程写到文本文件中,速度非常快,没有阻塞和延迟加载

1.首先在Model中建一个类MyExceptionAttribute.cs

public class MyExceptionAttribute : HandleErrorAttribute //继承
{
    public static Queue<Exception> exceptionQuese = new Queue<Exception>(); 
//重写父类方法,一抛异常就会执行这个方法 public override void OnException(ExceptionContext filterContext) { base.OnException(filterContext); exceptionQuese.Enqueue(filterContext.Exception);//将异常依靠添加到队列中 filterContext.HttpContext.Response.Redirect("/Error.html");//出现异常后转到错误页 } }

2.打开Global.asax文件,找到RegisterGlobalFilters并转到定义,让里面的方法new自己定义的类

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //filters.Add(new HandleErrorAttribute());
        filters.Add(new MyExceptionAttribute());
    }
}

3.在Global.asax文件下添加如下内容,当应用程序一打开时就执行一个线程,使用线程池,好处是为了避免线程频繁的创建,节省CPU耗用内存

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        log4net.Config.XmlConfigurator.Configure();//读取Log4Net配置信息
        AreaRegistration.RegisterAllAreas();

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

        //string fileLogPath = Server.MapPath("/App_Data/");
        //WaitCallback
        ThreadPool.QueueUserWorkItem((a) =>
        {
            while (true)
            {
                if (MyExceptionAttribute.ExceptionQueue.Count > 0)
                {
                    Exception ex = MyExceptionAttribute.ExceptionQueue.Dequeue();//出队
                    //string fileName = DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
                    //File.AppendAllText(fileLogPath + fileName, ex.ToString(), Encoding.Default);
                    ILog logger = LogManager.GetLogger("errorMsg");
                    logger.Error(ex.ToString());
                }
                else
                {
                    Thread.Sleep(3000);//如果队列中没有数据,休息避免造成CPU的空转.
                }
            }
        });
    }
}

4.打开Web.config,在configuration---configSections节点内添加

<configuration>
  <configSections>
    <!--Log4Net配置-->
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>

紧跟着在上面的</configSections>后面添加如下内容

    <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="ERROR"/>
    </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>
</configuration>

5.建一个控制器Test测试一下

public ActionResult Test()
{
    int a = 2;
    int b = 0;
    int c = a / b;
    return Content(c.ToString());
}