asp.net mvc实现 错误异常记录功能

来源:互联网 发布:宜家值得的买 知乎 编辑:程序博客网 时间:2024/05/17 12:05

创建LogExceptionAttribute 类,继承HandleErrorAttribute 错误异常过滤器

using System;using System.Web.Mvc;namespace SXF.Utils.MVC{    /// <summary>    /// 错误日志记录    /// </summary>    [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]    public class LogExceptionAttribute : HandleErrorAttribute    {        public override void OnException(ExceptionContext filterContext)        {            if (!filterContext.ExceptionHandled)            {                #region 记录错误日志                string controllerName = (string)filterContext.RouteData.Values["controller"];                string actionName = (string)filterContext.RouteData.Values["action"];                string msgTemplate = string.Format("在执行 controller[{0}] 的 action[{1}] 时产生异常", controllerName, actionName);                EventLog.LogItem item = new EventLog.LogItem();                item.Title = msgTemplate;                LogManage.WriteException(filterContext.Exception, item);                #endregion            }            base.OnException(filterContext);        }    }}

此方法中用到了EventLog类中的方法,代码如下:

using System;using System.Collections.Generic;using System.Collections.Specialized;using System.Configuration;using System.IO;using System.Text;using System.Web;namespace SXF.Utils{    /// <summary>    /// 写日志    /// 不想自动记录Context信息请调用Log(string message, string typeName, false)    /// </summary>    public class EventLog    {        /// <summary>        /// 是否使用上下文信息写日志        /// </summary>        static bool UseContext = true;        static string _thisDomain = "";        #region LogItem        [Serializable]        public class LogItem        {            public DateTime Time            {                get;                set;            }            public string Title            {                get;                set;            }            public string Detail            {                get;                set;            }            public string RequestUrl            {                get;                set;            }            public string UrlReferrer            {                get;                set;            }            public string HostIP            {                get;                set;            }            public string UserAgent            {                get;                set;            }            public override string ToString()            {                string s = Time.ToString("yyyy-MM-dd HH:mm:ss");                if (string.IsNullOrEmpty(Title))                {                    Title = Detail;                    Detail = "";                }                if (!string.IsNullOrEmpty(Title))                {                    s += "  " + Title;                }                if (!string.IsNullOrEmpty(RequestUrl))                {                    s += "\r\nUrl:" + RequestUrl;                }                if (!string.IsNullOrEmpty(UrlReferrer))                {                    s += "\r\nUrlReferrer:" + UrlReferrer;                }                if (!string.IsNullOrEmpty(HostIP))                {                    s += "\r\nHostIP:" + HostIP;                }                if (!string.IsNullOrEmpty(UserAgent))                {                    s += "\r\n" + UserAgent;                }                if (!string.IsNullOrEmpty(Detail))                {                    s += "\r\n" + Detail;                }                s += "\r\n";                return s;            }        }        #endregion        static object lockObj = new object();        /// <summary>        /// 检查目录并建立        /// </summary>        /// <param name="path"></param>        public static void CreateFolder(string path)        {            if (path.IsNullOrEmpty())            {                return;            }            string folder = "";            string[] arry = path.Split('\\');            for (int i = 0; i < arry.Length; i++)            {                folder += arry[i] + "\\";                if (!Directory.Exists(folder))                    Directory.CreateDirectory(folder);            }        }        /// <summary>        /// 自定义文件名前辍写入日志        /// </summary>        /// <param name="message"></param>        /// <param name="typeName"></param>        /// <param name="useContext"></param>        /// <returns></returns>        public static bool Log(string message, string typeName, bool useContext)        {            LogItem logItem = new LogItem();            logItem.Detail = message;            return Log(logItem, typeName, useContext);        }        public static bool Log(string message, string typeName)        {            return Log(message, typeName, true);        }        /// <summary>        /// 指定日志类型名生成日志        /// </summary>        /// <param name="logItem"></param>        /// <param name="typeName"></param>        /// <returns></returns>        public static bool Log(LogItem logItem, string typeName)        {            return Log(logItem, typeName, true);        }        /// <summary>        /// 指定日志类型名生成日志        /// </summary>        /// <param name="logItem"></param>        /// <param name="typeName"></param>        /// <param name="useContext">是否使用当前上下文信息</param>        /// <returns></returns>        public static bool Log(LogItem logItem, string typeName, bool useContext)        {            string fileName = DateTime.Now.ToString("yyyy-MM-dd");            if (!string.IsNullOrEmpty(typeName))            {                fileName += "." + typeName;            }            HttpContext context = HttpContext.Current;            logItem.Time = DateTime.Now;            if (context != null)            {                try                {                    if (string.IsNullOrEmpty(_thisDomain))                    {                        _thisDomain = context.Request.Url.Host;                    }                    if (UseContext)                    {                        if (useContext)                        {                            logItem.HostIP = RequestHelper.GetCdnIP();                            logItem.RequestUrl = context.Request.Url.ToString();                            logItem.UserAgent = context.Request.UserAgent;                            logItem.UrlReferrer = context.Request.UrlReferrer + "";                        }                    }                }                catch                {                }            }            return WriteLog(GetLogFolder(), logItem, fileName);        }        /// <summary>        /// 生成日志,默认文件名        /// </summary>        /// <param name="message"></param>        /// <param name="sendToServer">是否发送到服务器</param>        /// <returns></returns>        public static bool Log(string message, bool sendToServer)        {            //if (sendToServer)            //{            //    SendToServer(message, "");            //}            return WriteLog(message);        }        /// <summary>        /// 生成日志,默认文件名        /// </summary>        /// <param name="message"></param>        /// <returns></returns>        public static bool Log(string message)        {            return WriteLog(message);        }        /// <summary>        /// 生成日志,文件名以Error开头        /// </summary>        /// <param name="message"></param>        /// <returns></returns>        public static bool Error(string message)        {            return Log(message, "Error");        }        /// <summary>        /// 生成日志,文件名以Info开头        /// </summary>        /// <param name="message"></param>        /// <returns></returns>        public static bool Info(string message)        {            return Log(message, "Info");        }        /// <summary>        /// 生成日志,文件名以Debug开头        /// </summary>        /// <param name="message"></param>        /// <returns></returns>        public static bool Debug(string message)        {            return Log(message, "Debug");        }        /// <summary>        /// 在当前网站目录生成日志        /// </summary>        /// <param name="message"></param>        public static bool WriteLog(string message)        {            return Log(message, "");        }        static bool Writing = false;        //static DateTime lastWriteTime = DateTime.Now;        static Dictionary<string, LogItemArry> logCaches = new Dictionary<string, LogItemArry>();        static System.Timers.Timer timer;        private static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)        {            if (!Writing)            {                WriteLogFromCache();            }        }        /// <summary>        /// 指定路径,文件名,写入日志        /// </summary>        /// <param name="path"></param>        /// <param name="logItem"></param>        /// <param name="fileName"></param>        /// <returns></returns>        public static bool WriteLog(string path, LogItem logItem, string fileName)//建立日志        {            try            {                if (timer == null)                {                    timer = new System.Timers.Timer();                    timer.Interval = 2000;                    timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);                    timer.Start();                }                if (!System.IO.Directory.Exists(path))                    CreateFolder(path);                string filePath = "";                filePath = path + fileName + ".txt";                if (!logCaches.ContainsKey(filePath))                    logCaches.Add(filePath, new LogItemArry() { savePath = filePath });                logCaches[filePath].Add(logItem);                return true;            }            catch            {                return false;            }        }        public static string LastError;        public static void WriteLogFromCache()        {            lock (lockObj)            {                Writing = true;                //累加上次记录的日志                if (logCaches.Count > 0)                {                    Dictionary<string, LogItemArry> list = new Dictionary<string, LogItemArry>(logCaches);                    foreach (KeyValuePair<string, LogItemArry> entry in list)                    {                        LogItemArry logitemArry = entry.Value;                        LastError = null;                        try                        {                            WriteLine(logitemArry.ToString(), entry.Key);                        }                        catch (Exception ero)                        {                            LastError = ero.ToString();                        }                        logCaches.Remove(entry.Key);                    }                }                //System.Threading.Thread.Sleep(6000);                Writing = false;            }        }        /// <summary>        /// 写信息到指定文件        /// </summary>        /// <param name="message"></param>        /// <param name="filePath"></param>        private static void WriteLine(string message, string filePath)        {            using (FileStream fs = File.OpenWrite(filePath))            {                //根据上面创建的文件流创建写数据流                StreamWriter w = new StreamWriter(fs, System.Text.Encoding.Default);                //设置写数据流的起始位置为文件流的末尾                w.BaseStream.Seek(0, SeekOrigin.End);                //w.Write(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));                w.Write(message);                w.Flush();                w.Close();            }            Console.WriteLine(message);        }        static string secondFolder = null;        /// <summary>        /// 获取日志二级目录        /// </summary>        /// <returns></returns>        public static string GetSecondFolder()        {            if (secondFolder == null)            {                string address = RequestHelper.GetServerIp();                string[] arry = address.Split('.');                secondFolder = arry[arry.Length - 1];            }            return secondFolder;        }        static string rootPath = null;        /// <summary>        /// 获取日志绝对目录        /// </summary>        /// <returns></returns>        public static string GetLogFolder()        {            if (rootPath == null)            {                rootPath = System.Web.Hosting.HostingEnvironment.MapPath(@"\log\");                if (string.IsNullOrEmpty(rootPath))                {                    rootPath = AppDomain.CurrentDomain.BaseDirectory + @"\log\";                }                rootPath += GetSecondFolder() + @"\";                //如果节点有设置,则按节点设置读取                NameValueCollection appSettings = ConfigurationManager.AppSettings;                string settingPath = appSettings["EventLogFolder"];                if (!string.IsNullOrEmpty(settingPath))                {                    rootPath = settingPath + @"\";                }            }            return rootPath;        }        /// <summary>        /// 项集合        /// </summary>        public class LogItemArry        {            public string savePath;            List<LogItem> logs = new List<LogItem>();            public void Add(LogItem log)            {                logs.Add(log);            }            public override string ToString()            {                StringBuilder sb = new StringBuilder();                foreach (LogItem item in logs)                {                    sb.Append(item.ToString());                }                return sb.ToString() + "\r\n";            }        }    }}

用到了LogManage 类的方法,代码如下:

using System;using System.Text;using System.Web;namespace SXF.Utils.MVC{    /// <summary>    /// mvc日志管理    /// </summary>    public class LogManage    {        public static Exception GetInnerException(Exception exp)        {            if (exp.InnerException != null)            {                exp = exp.InnerException;                return GetInnerException(exp);            }            return exp;        }        static long exceptionId = 0;        static object lockObj = new object();        /// <summary>        /// 内部记录日志        /// </summary>        /// <param name="ero"></param>        /// <returns></returns>        static string InnerLogException(Exception ero, EventLog.LogItem item)        {            string host = HttpContext.Current.Request.Url.Host.ToUpper();            string errorCode = host.Replace(".", "_");            lock (lockObj)            {                exceptionId += 1;                errorCode += ":" + EventLog.GetSecondFolder() + ":" + exceptionId;            }            ero = GetInnerException(ero);            item.Title = item.Title + ",错误代码:" + errorCode;            if (ero != null)            {                item.Detail = ero.Message + "\r\n" + ero.StackTrace + "\r\n";            }            EventLog.Log(item, "Error");            if (host == "LOCALHOST")            {                return errorCode;            }            return errorCode;        }        /// <summary>        /// 页面输出并写入错误日志        /// </summary>        /// <param name="ero"></param>        public static void WriteException(Exception ero, EventLog.LogItem item)        {            //EventLog.Log("start1", "error");            bool logError = true;            if (ero is HttpException)            {                HttpException he = ero as HttpException;                int code = he.GetHttpCode();                if (code == 404)                {                    logError = false;                }            }            if (ero is HttpRequestValidationException)            {                logError = false;            }            //EventLog.Log("start2", "error");            string errorCode = string.Empty;            if (logError)            {                //EventLog.Log("start6", "error");                errorCode = InnerLogException(ero, item);            }        }    }}

写好后需要在FilterConfig 中注册:

public static class FilterConfig    {        public static void RegisterGlobalFilters(GlobalFilterCollection filters)        {            //错误处理            filters.Add(new HandleErrorAttribute());            //日志记录            filters.Add(new SXF.Utils.MVC.LogExceptionAttribute());                   }    }

global.asax.cs中已经在application_start中默认有调用代码:

FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

另外 web.config 中设置:

<customErrors mode="Off" />


这样就设置好了,一旦在网站中出现mvc 错误,会在网站根目录的 log 文件夹下,自动创建一个类似这样的txt 日志文件:2017-08-02.Error.txt ,每天都会创建一个。若没创建,要么是没有log 文件夹,要么是log 文件夹网站默认用户没创建文件及文件夹的权限

原创粉丝点击