log4net是.Net下一个非常优秀的开源日志记录组件。log4net记录日志的功能非常强大。它可以将日志分不同的等级,以不同的格式,输出到不同的媒介。
在NuGet程序包中下载log4Net组件,如下图所示:
打开Web.config文件,在<configSections>中添加如下配置节点:
<configSections><section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/></configSections>
紧靠上图节点,添加如下配置节点:
<!--log4Net的另一种配置:动态配置--><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"><!--这里进一步限制了日志级别,只有在大于等于DEBUG的情况下才会记录日志--><level value="DEBUG"/></logger><appender name="SysAppender" type="log4net.Appender.RollingFileAppender,log4net" ><!--日志放在项目的App_Data文件夹--><param name="File" value="App_Data/" /><!--日志以追加形式记录--><param name="AppendToFile" value="true" /><!--日期作为回滚:日期排序--><param name="RollingStyle" value="Date" /><!--设置日志文件名称的生成规则 --><param name="DatePattern" value=""Logs_"yyyyMMdd".txt"" /><!--日志文件是否静态:否--><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=" ----------------------header-------------------------- " /><param name="Footer" value=" ----------------------footer-------------------------- " /></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配置结束-->
注意: <configSections> 必须是 <configuration>元素下第一个子元素,并且是唯一的。不然会报错,报错界面如下所示:
在Global.asax.cs文件中的Application_Start方法中,插入如下代码:
log4net.Config.XmlConfigurator.Configure();
考虑到记录日志会存在并发的问题,这里通过队列的方式来记录日志:把所有产生的日志信息存放到一个队列里,然后通过新建一个线程不断的从这个队列里读取异常信息,然后往日志里写,这也就是所谓的生产者--消费者模式。
新建一个类MyErrorAttribute ,继承自全局异常类HandleErrorAttribute,,如下图所示:
public class MyErrorAttribute:HandleErrorAttribute{public static Queue<Exception> ExceptionQueue = new Queue<Exception>();public override void OnException(ExceptionContext filterContext){ExceptionQueue.Enqueue(filterContext.Exception);base.OnException(filterContext);}}
在FilterConfig类中替换成 上图 自定义的 类:
public static void RegisterGlobalFilters(GlobalFilterCollection filters){//filters.Add(new HandleErrorAttribute());//注释掉系统默认的filters.Add(new MyErrorAttribute());}
在Global.asax.cs文件中的Application_Start方法中,再插入如下代码:
ThreadPool.QueueUserWorkItem(o =>{while (true){if (MyErrorAttribute.ExceptionQueue.Count > 0){Exception ex = MyErrorAttribute.ExceptionQueue.Dequeue();if (ex != null){log4net.ILog logger = log4net.LogManager.GetLogger("testError");logger.Error(ex.ToString());//将异常写入log4net}else{Thread.Sleep(50);}}else{Thread.Sleep(50);}}});
此时, Global.asax.cs文件中的Application_Start方法已经变成如下图所示的样子了:
protected void Application_Start(){log4net.Config.XmlConfigurator.Configure();AreaRegistration.RegisterAllAreas();FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);BundleConfig.RegisterBundles(BundleTable.Bundles);ThreadPool.QueueUserWorkItem(o =>{while (true){if (MyErrorAttribute.ExceptionQueue.Count > 0){Exception ex = MyErrorAttribute.ExceptionQueue.Dequeue();if (ex != null){log4net.ILog logger = log4net.LogManager.GetLogger("testError");logger.Error(ex.ToString());//将异常写入log4net}else{Thread.Sleep(50);}}else{Thread.Sleep(50);}}});}
接下去开始测试:在控制器中添加一段引发异常的代码,如下图所示:
public ActionResult About(){int result = 0;int x = 1, y = 0;result = x / y; //引发异常ViewBag.Message = "Your application description page.";return View();}
运行,系统跳转到error界面,如下图所示:
打开App_Data文件,查看日志文件如下所示:
至此为止,一个利用Log4Net记录系统异常的功能开发完成了。