一般情况下,我个人的习惯是不会把日志记录为txt文件,而是将错误日志保存到数据库方便自己查询,所以需要在数据库建一张日志表

引用 log4net (可直接通过nuget进行安装),然后准备一个 LoggerHelper类 用于对错误日志的数据记录,也方便之后记录自己需要捕获的异常或者其他调试信息

public class LoggerHelper
    { 
        private static string _ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();

        IRawLayout thread = new Layout2RawLayoutAdapter(new PatternLayout("%thread"));

        public static void Error(string ErrorMsg, Exception ex)
        {
            AdoNetAppender adoAppender = new AdoNetAppender();
            adoAppender.Name = "AdoNetAppender";
            adoAppender.CommandType = CommandType.Text;
            adoAppender.BufferSize = 1;
            adoAppender.ConnectionType = "System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
            adoAppender.ConnectionString = _ConnectionString;
            adoAppender.CommandText = @"INSERT INTO Pomelo_Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)";
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@log_date", DbType = DbType.DateTime, Layout = new RawTimeStampLayout() });
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@thread", DbType = DbType.String, Size = 255, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%thread")) });
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@log_level", DbType = DbType.String, Size = 50, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%level")) });
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@logger", DbType = DbType.String, Size = 255, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%logger")) });
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@message", DbType = DbType.String, Size = 4000, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%message")) });
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@exception", DbType = DbType.String, Size = 4000, Layout = new Layout2RawLayoutAdapter(new ExceptionLayout()) });
            adoAppender.ActivateOptions();
            BasicConfigurator.Configure(adoAppender);

            ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            log.Error(ErrorMsg, ex);

            adoAppender.Close();
        }

        public static void Info(string Msg)
        {
            AdoNetAppender adoAppender = new AdoNetAppender();
            adoAppender.Name = "AdoNetAppender";
            adoAppender.CommandType = CommandType.Text;
            adoAppender.BufferSize = 1;
            adoAppender.ConnectionType = "System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
            adoAppender.ConnectionString = _ConnectionString;
            adoAppender.CommandText = @"INSERT INTO Pomelo_Log ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)";
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@log_date", DbType = DbType.DateTime, Layout = new RawTimeStampLayout() });
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@thread", DbType = DbType.String, Size = 255, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%thread")) });
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@log_level", DbType = DbType.String, Size = 50, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%level")) });
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@logger", DbType = DbType.String, Size = 255, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%logger")) });
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@message", DbType = DbType.String, Size = 4000, Layout = new Layout2RawLayoutAdapter(new PatternLayout("%message")) });
            adoAppender.AddParameter(new AdoNetAppenderParameter { ParameterName = "@exception", DbType = DbType.String, Size = 4000, Layout = new Layout2RawLayoutAdapter(new ExceptionLayout()) });
            adoAppender.ActivateOptions();
            BasicConfigurator.Configure(adoAppender);

            ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            log.Info(Msg);

            adoAppender.Close();
        } 
    }

为了不用每次手动去获取错误异常,我们可以在 App_Start 文件夹下建一个全局过滤器配置类 FilterConfig.cs,来添加监控类

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

StatisticsTrackerAttribute类,当系统抛异常的时候,该类会自动监控捕获到异常并进行对应处理

    /// 
    /// 监控类
    /// 
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class StatisticsTrackerAttribute : ActionFilterAttribute, IExceptionFilter
    {
        private readonly string Key = "_thisOnActionMonitorLog_";
 
        #region 错误日志
        public void OnException(ExceptionContext filterContext)
        {
            if (!filterContext.ExceptionHandled)
            {
                string ControllerName = string.Format("{0}Controller", filterContext.RouteData.Values["controller"] as string);
                string ActionName = filterContext.RouteData.Values["action"] as string;
                string ErrorMsg = string.Format("在执行 [{0}] 的 [{1}] 时产生异常", ControllerName, ActionName);
                LoggerHelper.Error(ErrorMsg, filterContext.Exception);
            }
        }
        #endregion
    }

然后每当系统出现错误的时候,就会自动将系统捕获到的异常信息添加在数据库日志表中