在项目运维过程中,常常出现客户描述某个错误,无法说得很清楚,通常这种情况下,建议客户截图发给我们看,然后“看图说话”来答复错误,但是这么做,常常有个问题,是无法知道当时到底哪个地址,从那个IP,操作的具体哪个URL,都传递了什么参数,具体的错误是什么引起的。如果能记录下详细的错误环境相关的一些信息,以备运维和开发人员去查询问题,那就太方便了。于是我就想起来在我的应用中做这么一个小模块。实现随时可以查询到位所有的错误的详细信息(包括发生错误的时间、IP地址、错误记录、URL地址、详细错误信息)如下图所示:甚至我通过我的一个WebBrowser框架浏览此业务系统,自动截取当时系统的截图,这样能在业务部门及时没有发现错误的时候,也做到心里有数。
下面介绍一下实现方法:
1.在Global.asax代码文件中,添加如下函数
代码
1 protected void Application_Error(object sender, EventArgs e)
2 {
3 try
4 {
5 Exception objErr = Server.GetLastError().GetBaseException();
6 string err = "Error Caught in Application_Error event" +
7 "\nError in:" + Request.Url +
8 "\nError Message:" + objErr.Message +
9 "\nStack Trace:" + objErr.StackTrace +
10 "\nSource Ip:" + Request.UserHostAddress;
11 const string eventSource = "XXXX应用服务器";
12 if (!EventLog.SourceExists(eventSource))
13 EventLog.CreateEventSource(eventSource,eventSource);
14 EventLog.WriteEntry(eventSource, err, EventLogEntryType.Error);
15 //Server.ClearError();
16 }
17 catch (Exception exception)
18 {
19 sysConfig.PLog("Sys", "", exception.Message, "");
20 }
21 //在出现未处理的错误时运行的代码
22 Server.Transfer("~/Error.aspx");
23 }
2 {
3 try
4 {
5 Exception objErr = Server.GetLastError().GetBaseException();
6 string err = "Error Caught in Application_Error event" +
7 "\nError in:" + Request.Url +
8 "\nError Message:" + objErr.Message +
9 "\nStack Trace:" + objErr.StackTrace +
10 "\nSource Ip:" + Request.UserHostAddress;
11 const string eventSource = "XXXX应用服务器";
12 if (!EventLog.SourceExists(eventSource))
13 EventLog.CreateEventSource(eventSource,eventSource);
14 EventLog.WriteEntry(eventSource, err, EventLogEntryType.Error);
15 //Server.ClearError();
16 }
17 catch (Exception exception)
18 {
19 sysConfig.PLog("Sys", "", exception.Message, "");
20 }
21 //在出现未处理的错误时运行的代码
22 Server.Transfer("~/Error.aspx");
23 }
2.写一个Error.aspx作为标准页面,展示给用户看,另外在后台Error.aspx.cs处理错误的记录中主要处理错误代码如下:
错误处理代码
1 #region 标准错误处理
2 Exception objExp = HttpContext.Current.Server.GetLastError();
3 objExp.Source = HttpContext.Current.Request.Url.ToString();
4 //忽略采网际快车或其他网络工具下载带有书签的HTTP请求导致的异常]
5 if (HttpContext.Current.Request.Url.ToString().IndexOf("#") != -1)
6 {
7 //清除当前HTTP请求的所有错误
8 ToShowError(objExp, "您的请求是非法的,将被系统忽略");
9 HttpContext.Current.ClearError();
10 return;
11 }
12
13 //循环处理异常事件
14 for (Exception TempException = objExp; TempException != null; TempException = TempException.InnerException)
15 {
16 #region 如果系统检测到非法字符,则提示并返回
17 if (TempException.GetType().ToString() == "System.Web.HttpRequestValidationException")
18 {
19 //清除当前HTTP请求的所有错误
20 ToShowError(TempException, "系统检测到您输入了非法字符");
21 HttpContext.Current.ClearError();
22 //返回
23 return;
24 }
25 #endregion
26
27 #region 异常为内存溢出
28 if (TempException.GetType().ToString() == "System.OutOfMemoryException")
29 {
30 //清除当前HTTP请求的所有错误
31 ToShowError(TempException, "服务器资源耗尽,请稍候重试!");
32 HttpContext.Current.ClearError();
33 //返回
34 break;
35 }
36 #endregion
37
38 #region 由SQLServer返回的警告或或错误引发的异常
39 if (TempException.GetType().ToString() == "System.Data.SqlClient.SqlException")
40 {
41 byte ErrLevel = ((System.Data.SqlClient.SqlException)TempException).Class;
42 int Number = ((System.Data.SqlClient.SqlException)TempException).Number;
43
44 //严重程度处理 [数据库服务器已经关闭]
45 //Number == 17 [SQL Server 不存在或访问被拒绝]
46 //Number == 11 [常规网络错误。请检查您的网络文档]
47 if (ErrLevel == 20 && (Number == 17 || Number == 11))
48 {
49 ToShowError(TempException, "数据库服务器已经关闭,请稍候重试!");
50 //清除当前HTTP请求的所有错误
51 HttpContext.Current.ClearError();
52 //返回
53 return;
54 }
55
56 //严重程度处理 [数据库服务器正在关闭]
57 //Number == 6002 [SHUTDOWN 正在进行。请注销]
58 if (ErrLevel == 16 && Number == 6002)
59 {
60 ToShowError(TempException, "数据库服务器正在关闭,请稍候重试!");
61 //清除当前HTTP请求的所有错误
62 HttpContext.Current.ClearError();
63 //返回
64 return;
65 }
66
67 //严重程度处理 [系统正在登陆数据库服务器]
68
69
70 //输出
71 ToShowError(TempException, "系统正在登陆数据库服务器,请稍候重试!");
72
73 //返回
74 return;
75 }
76 #endregion
77
78 #region 框架异常
79 if (TempException.GetType().ToString() == "System.Web.HttpUnhandledException")
80 {
81 if (TempException.InnerException != null)
82 {
83 ToShowError(TempException.InnerException, "框架异常!");
84 }
85 else
86 {
87 ToShowError(TempException, "框架异常");
88 }
89 HttpContext.Current.ClearError();
90 return;
91 }
92 #endregion
93
94 //其他异常处理
95 ToShowError(TempException, "");
96 }
97 #endregion
2 Exception objExp = HttpContext.Current.Server.GetLastError();
3 objExp.Source = HttpContext.Current.Request.Url.ToString();
4 //忽略采网际快车或其他网络工具下载带有书签的HTTP请求导致的异常]
5 if (HttpContext.Current.Request.Url.ToString().IndexOf("#") != -1)
6 {
7 //清除当前HTTP请求的所有错误
8 ToShowError(objExp, "您的请求是非法的,将被系统忽略");
9 HttpContext.Current.ClearError();
10 return;
11 }
12
13 //循环处理异常事件
14 for (Exception TempException = objExp; TempException != null; TempException = TempException.InnerException)
15 {
16 #region 如果系统检测到非法字符,则提示并返回
17 if (TempException.GetType().ToString() == "System.Web.HttpRequestValidationException")
18 {
19 //清除当前HTTP请求的所有错误
20 ToShowError(TempException, "系统检测到您输入了非法字符");
21 HttpContext.Current.ClearError();
22 //返回
23 return;
24 }
25 #endregion
26
27 #region 异常为内存溢出
28 if (TempException.GetType().ToString() == "System.OutOfMemoryException")
29 {
30 //清除当前HTTP请求的所有错误
31 ToShowError(TempException, "服务器资源耗尽,请稍候重试!");
32 HttpContext.Current.ClearError();
33 //返回
34 break;
35 }
36 #endregion
37
38 #region 由SQLServer返回的警告或或错误引发的异常
39 if (TempException.GetType().ToString() == "System.Data.SqlClient.SqlException")
40 {
41 byte ErrLevel = ((System.Data.SqlClient.SqlException)TempException).Class;
42 int Number = ((System.Data.SqlClient.SqlException)TempException).Number;
43
44 //严重程度处理 [数据库服务器已经关闭]
45 //Number == 17 [SQL Server 不存在或访问被拒绝]
46 //Number == 11 [常规网络错误。请检查您的网络文档]
47 if (ErrLevel == 20 && (Number == 17 || Number == 11))
48 {
49 ToShowError(TempException, "数据库服务器已经关闭,请稍候重试!");
50 //清除当前HTTP请求的所有错误
51 HttpContext.Current.ClearError();
52 //返回
53 return;
54 }
55
56 //严重程度处理 [数据库服务器正在关闭]
57 //Number == 6002 [SHUTDOWN 正在进行。请注销]
58 if (ErrLevel == 16 && Number == 6002)
59 {
60 ToShowError(TempException, "数据库服务器正在关闭,请稍候重试!");
61 //清除当前HTTP请求的所有错误
62 HttpContext.Current.ClearError();
63 //返回
64 return;
65 }
66
67 //严重程度处理 [系统正在登陆数据库服务器]
68
69
70 //输出
71 ToShowError(TempException, "系统正在登陆数据库服务器,请稍候重试!");
72
73 //返回
74 return;
75 }
76 #endregion
77
78 #region 框架异常
79 if (TempException.GetType().ToString() == "System.Web.HttpUnhandledException")
80 {
81 if (TempException.InnerException != null)
82 {
83 ToShowError(TempException.InnerException, "框架异常!");
84 }
85 else
86 {
87 ToShowError(TempException, "框架异常");
88 }
89 HttpContext.Current.ClearError();
90 return;
91 }
92 #endregion
93
94 //其他异常处理
95 ToShowError(TempException, "");
96 }
97 #endregion
基本工作就完成了。事实证明,收集错误,对于快速定位问题,分析问题,能极大的提高效率。另外,通过收集错误,才发现,以前认为不会出现问题的页面,其实在偶尔会因为url参数等问题,是会出错的,之前还经常欺负业务部门,说决定不可能出现这样的问题,但是如果自己有错误机制,就会在武断的说这个话之前,先去看下服务器里面记录的错误,会更客观。而不是说,现在无法定位问题,等你下次出现这个问题的时候,来告诉我,别管页面,我给你看。