您的位置:首页 > 编程语言 > ASP

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

2017-08-29 09:39 513 查看
创建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 文件夹网站默认用户没创建文件及文件夹的权限
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  错误日志 自定义