.NET MVC项目安装log4net 并进行异常处理
一.安装log4net并进行相应的配置
1.安装log4net
2.在项目中添加log4net.config配置文件
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net-net-2.0"/> </configSections> <log4net> <root> <level value="ALL" /> <appender-ref ref="LogFileAppender" /> <!--<appender-ref ref="EventLogAppender" />--> </root> <!--定义输出到文件--> <appender name ="LogFileAppender" type="log4net.Appender.RollingFileAppender"> <!--定义文件存放位置--> <param name="File" value ="App_Data\"/> <param name="AppendToFile" value="true" /> <param name="MaxSizeRollBackups" value="100" /> <param name="MaxFileSize" value="10240" /> <param name="StaticLogFileName" value="false" /> <!--文件名格式--> <param name="DatePattern" value="yyyy.MM.dd'.txt'" /> <param name="RollingStyle" value ="Date" /> <!--不以独占方式记录日志,仅在记录每个日志的最短时间内锁定,因为部署到服务器上遇到了文件被占用无法下载日志--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <layout type="log4net.Layout.PatternLayout"> <!--定义输出格式--> <!--示例 2018-08-20 12:10:49,348 -线程ID:[21] 日志级别:[INFO ] : [日志信息]--> <param name="ConversionPattern" value="%date 调用对象:[%logger ] 线程ID:[%thread] 日志级别:[%-5level] : [%message]%newline"/> </layout> <!--过滤级别 FATAL > ERROR > WARN > INFO > DEBUG--> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="DEBUG" /> <param name="LevelMax" value="FATAL" /> </filter> </appender> <!--定义输出到 windows 事件中--> <appender name="EventLogAppender" type="log4net.Appender.EventLogAppender"> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"></conversionPattern> </layout> </appender> </log4net> </configuration>
3.在Global.asax的Application_Start中进行注册
log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("/log4net.config")));
4.编写LogHelper帮助类
public class LogHelper { private ILog _log4Net = null; private const string DEFAULT_LOGGER_NAME = "Logger"; /// <summary> /// Prevents a default instance of the <see cref="LogWriter"/> class from being created. /// </summary> /// <param name="log4NetInstance">The log4net instance to be used.</param> private LogHelper(ILog log4NetInstance) { _log4Net = log4NetInstance; } /// <summary> /// Gets a logger with the specified configuration name. /// </summary> /// <param name="configName">Name of the logger in the configuration.</param> /// <returns>The logger obtained.</returns> /// <exception cref="System.Configuration.ConfigurationException">Thrown when no logger with the specified configuration name was found.</exception> public static LogHelper GetLogger(string configName) { var logger = LogManager.GetLogger(configName); if (logger == null) { throw new ArgumentException(string.Format("No logger configuration named '{0}' was found in the configuration.", configName), "configName"); } return new LogHelper(logger); } /// <summary> /// Gets the default. /// </summary> public static LogHelper Default { get { return GetLogger(DEFAULT_LOGGER_NAME); } } /// <summary> /// Writes an information level logging message. /// </summary> /// <param name="message">The message to be written.</param> public void WriteInfo(object message) { _log4Net.Info(message); } /// <summary> /// Writes a warning level logging message. /// </summary> /// <param name="message">The message to be written.</param> public void WriteWarning(object message) { _log4Net.Warn(message); } /// <summary> /// Writes a warning level logging message. /// </summary> /// <param name="message">The message to be written.</param> /// <param name="exception">The exception.</param> public void WriteWarning(object message, System.Exception exception) { _log4Net.Warn(message, exception); } /// <summary> /// Writes the error. /// </summary> /// <param name="message">The message to be written.</param> public void WriteError(object message) { _log4Net.Error(message); } /// <summary> /// Writes the error level logging message.. /// </summary> /// <param name="message">The message to be written.</param> /// <param name="exception">The exception.</param> public void WriteError(object message, System.Exception exception) { _log4Net.Error(message, exception); } /// <summary> /// Writes the fatal error level logging message.. /// </summary> /// <param name="message">The message to be written.</param> public void WriteFatal(object message) { _log4Net.Fatal(message); } /// <summary> /// Writes the fatal error level logging message.. /// </summary> /// <param name="message">The message to be written.</param> /// <param name="exception">The exception.</param> public void WriteFatal(object message, System.Exception exception) { _log4Net.Fatal(message, exception); } public void DeleteLog() { string logDirPath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Log"); if (!Directory.Exists(logDirPath)) return; int days = 30; foreach (string filePath in Directory.GetFiles(logDirPath)) { DateTime dt; DateTime.TryParse(Path.GetFileNameWithoutExtension(filePath).Replace(@"Log\", "").Replace(".", "-"), out dt); if (dt.AddDays(days).CompareTo(DateTime.Now) < 0) { File.Delete(filePath); } } } }
5.写入日志
LogHelper.GetLogger(typeof(MyHandleErrorAttribute).ToString()).WriteError($"在相应{httpContext.Request.Url.AbsoluteUri}时出现异常! 异常信息:{filterContext.Exception.Message}");
二.自定义异常处理
1.通过重写HandleErrorAttribute中的OnException方法,来定制自己的异常处理
public class MyHandleErrorAttribute:HandleErrorAttribute { public override void OnException(ExceptionContext filterContext) { var httpContext = filterContext.HttpContext; if (!filterContext.ExceptionHandled) //错误没有被别的HandleErrorAttribute处理 { //日志记录 LogHelper.GetLogger(typeof(MyHandleErrorAttribute).ToString()).WriteError($"在相应{httpContext.Request.Url.AbsoluteUri}时出现异常! 异常信息:{filterContext.Exception.Message}"); filterContext.Result = new ViewResult() { ViewName= "/Views/Share/ErrorPage.cshtml" }; //返回指定的错误页 filterContext.ExceptionHandled = true; } } }
2.全局注册上面编写的 MyHandleErrorAttribute
//在App_Start里添加FilterConfig文件 public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new MyHandleErrorAttribute()); } } //在Application_Start添加上面的配置 protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); }
三.用Application_Error实现异常处理
上面通过自定义的异常处理,存在一定的问题,有的异常可能拦截不到,例如路径输入错误等,不能进行异常的处理。通过Application_Error
可以对所有的异常进行拦截,但所有没有处理的错误都会导致这个Application_Error方法的执行,所以在这个方法中进行异常处理,能捕获到整个系统中没被处理的异常
//在Global.asax进行编写 protected void Application_Error(object sender,EventArgs e) { Exception exception = Server.GetLastError(); LogHelper.GetLogger(typeof(MvcApplication).ToString()).WriteError($"{Context.Request.Url.AbsoluteUri}出现错误,错误信息为:{exception}"); //进行日志记录 Response.ContentType = "text/html"; Response.Write("<h1>System Is Error</h1>"); Server.ClearError(); }