1.管理Nuget程序包,安装Log4
2.log4net.config 的编写(有异常日志类和信息日志类,按需要配置)
<?xml version="1.0" encoding="utf-8"?> <configuration> <log4net> <!-- 错误日志类--> <logger name="logerror"> <level value="ALL" /> <appender-ref ref="ErrorAppender" /> </logger> <!-- 错误日志附加介质--> <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender"> <!--日志文件路径--> <param name="File" value="Log\\LogError\\" /> <!--是否是向文件中追加日志--> <param name="AppendToFile" value="true" /> <!--log保留天数--> <param name="MaxSizeRollBackups" value="1000" /> <!--最大文件大小--> <param name="MaxFileSize" value="10240" /> <!--日志文件名是否是固定不变的--> <param name="StaticLogFileName" value="false" /> <!--日志文件名格式为:2008-08-31.log--> <param name="DatePattern" value="yyyy-MM-dd".htm"" /> <!--日志根据日期滚动--> <param name="RollingStyle" value="Date" /> <!--信息日志布局--> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="<HR COLOR=red>%n【异常时间】:%d [%t] <BR>%n【异常级别】:%-5p <BR>%n%m <BR>%n <HR Size=1>" /> </layout> </appender> </log4net> </configuration>
cofig配置好之后,在startup里面,创建log仓储
public static ILoggerRepository repository { get; set; } public Startup(IConfiguration configuration) { Configuration = configuration; repository = LogManager.CreateRepository("LogRepository");//创建一个Log仓储 XmlConfigurator.Configure(repository, new FileInfo("log4net.config"));//文件流读取log配置文件 InitRepository.LogRepository = repository; }
运行后,会在程序目录创建文件夹和html文件
现在我们写一个异常,将异常写入到日志里。
首先我们需要写一个全局异常的过滤器GlobalExceptions,捕获程序异常
//全局异常捕获过滤器 public class GlobalExceptions : IExceptionFilter { private readonly IHostingEnvironment _env; public GlobalExceptions(IHostingEnvironment env) { _env = env; } /// <summary> /// 当出现异常的时候,会调用该方法捕获异常,该方法是对IExceptionFilter里面的OnException的实现 /// </summary> /// <param name="context"></param> public void OnException(ExceptionContext context) { //将异常上下文给到LogHelper写入 LogHelper.ErrorLog(context.Exception); } }
这里我们需要将过滤器注册下
OnException方法是对IExceptionFilter里同名方法的实现,当抛出异常的时候就会进入这里了,我们将异常上下文给到LogHelper,帮忙写入到日志文件中
LogHelper部分代码
public class InitRepository { public static ILoggerRepository LogRepository { get; set; } } public class LogHelper { //全局异常错误记录持久化 private static readonly ILog logerror = LogManager.GetLogger(InitRepository.LogRepository.Name, "logerror"); //自定义操作记录 //private static readonly ILog loginfo = LogManager.GetLogger(InitRepository.LogRepository.Name, "loginfo"); #region 全局异常错误记录持久化 /// <summary> /// 全局异常错误记录持久化 /// </summary> /// <param name="ex">异常上下文</param> public static void ErrorLog(Exception ex) { string errorMsg = string.Format("【异常信息】:{0} <br>【异常类型】:{1} <br>【堆栈调用】:{2} <br>", new object[] {ex.Message, ex.GetType().Name, ex.StackTrace }); errorMsg = errorMsg.Replace("\r\n", "<br>"); errorMsg = errorMsg.Replace("位置", "<strong style=\"color:red\">位置</strong>"); logerror.Error(errorMsg); } #endregion #region 自定义操作记录 /// <summary> /// 自定义操作记录,与仓储中的增删改的日志是记录同一张表,操作记录暂不需要 /// </summary> /// <param name="throwMsg"></param> /// <param name="ex"></param> //public static void WriteLog(string throwMsg, Exception ex) //{ // string errorMsg = string.Format("【抛出信息】:{0} <br>【异常类型】:{1} <br>【异常信息】:{2} <br>【堆栈调用】:{3}", new object[] { throwMsg, // ex.GetType().Name, ex.Message, ex.StackTrace }); // errorMsg = errorMsg.Replace("\r\n", "<br>"); // errorMsg = errorMsg.Replace("位置", "<strong style=\"color:red\">位置</strong>"); // logerror.Error(errorMsg); //} #endregion }
现在我们去写一个异常
这里重点说下,写异常的时候不能加async,这个标识会在主线程下创建一个子线程,当没有await 返回程序执行结果或异常的时候,异常会直接死在子线程里,不回被全局异常捕获到,大概就是下面这个意思
我们去掉标识再执行这个异常,监测主线程的过滤器就能检测到异常,Loghelper将异常信息写入文件