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

创建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 文件夹网站默认用户没创建文件及文件夹的权限

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值