在项目运维过程中,常常出现客户描述某个错误,无法说得很清楚,通常这种情况下,建议客户截图发给我们看,然后“看图说话”来答复错误,但是这么做,常常有个问题,是无法知道当时到底哪个地址,从那个IP,操作的具体哪个URL,都传递了什么参数,具体的错误是什么引起的。如果能记录下详细的错误环境相关的一些信息,以备运维和开发人员去查询问题,那就太方便了。于是我就想起来在我的应用中做这么一个小模块。实现随时可以查询到位所有的错误的详细信息(包括发生错误的时间、IP地址、错误记录、URL地址、详细错误信息)如下图所示:甚至我通过我的一个WebBrowser框架浏览此业务系统,自动截取当时系统的截图,这样能在业务部门及时没有发现错误的时候,也做到心里有数。
下面介绍一下实现方法:
1.在Global.asax代码文件中,添加如下函数
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处理错误的记录中主要处理错误代码如下:
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参数等问题,是会出错的,之前还经常欺负业务部门,说决定不可能出现这样的问题,但是如果自己有错误机制,就会在武断的说这个话之前,先去看下服务器里面记录的错误,会更客观。而不是说,现在无法定位问题,等你下次出现这个问题的时候,来告诉我,别管页面,我给你看。
闲来无事,把老东西翻出来写写,希望对大家有用,如果有说的不对的地方,欢迎大家砸砖。