设计一个错误处理类库
上次发了“写一个监测跟踪的类库”的帖子,这次贴错误处理的类库
上次的帖子地址如下
http://onlytiancai.cnblogs.com/archive/2005/07/30/203649.html
其实写这些文章没啥用,就是开拓开拓思路而已,微软已经发布了几个好用的应用程序快,什么blok,我也记不住那些英文。把偶用的错误处理类库贴出来,是让大家批评批评看看有哪些设计不当,考虑不全的地方,大家多多指点一下,比直接用那些现成的东西有收获应该,对吧。
/*
* Enumeration : GWExceptionMessages
* Namespace : GW.MonitorServices.Logging
* Assembly : GW.MonitorServices.Logging
* Author : Kevin Hoffman
* Description : Enumeration containing index values into the string resource containing the standardized error messages
*/
using System;
namespace GW.MonitorServices.Logging
{
/// <summary>
/// 这是个保存错误类型的枚举,和ErrorMessages.resx资源文件里的
/// 详细错误描述相对应
/// </summary>
public enum GWExceptionMessages
{
DefaultMessage = 1000,
DbLogFailed = 1001,
SeeDatabase = 1002,
PersistenceFailure = 1003
}
}
* Enumeration : GWExceptionMessages
* Namespace : GW.MonitorServices.Logging
* Assembly : GW.MonitorServices.Logging
* Author : Kevin Hoffman
* Description : Enumeration containing index values into the string resource containing the standardized error messages
*/
using System;
namespace GW.MonitorServices.Logging
{
/// <summary>
/// 这是个保存错误类型的枚举,和ErrorMessages.resx资源文件里的
/// 详细错误描述相对应
/// </summary>
public enum GWExceptionMessages
{
DefaultMessage = 1000,
DbLogFailed = 1001,
SeeDatabase = 1002,
PersistenceFailure = 1003
}
}
/*
* Class : FileErrorLog
* Namespace : GW.MonitorServices.Logging
* Assembly : GW.MonitorServices.Logging
* Author : Kevin Hoffman
* Description : Class responsible for logging error information to HTML text files as backup/alternate to DB error logging.
*/
using System;
using System.Configuration;
using System.Diagnostics;
using System.Reflection;
namespace GW.MonitorServices.Logging
{
/// <summary>
/// 把错误持久到文本文件的类,这个类用来把错误信息或指定信息记录在一个文本文件里,并
/// 使用HTML格式,方便你查看
/// </summary>
public class FileErrorLog
{
/// <summary>
/// 设置一个读写锁,防治在操作日志文本文件的时候别人也使用,这样就不会出现并发问题
/// </summary>
private static readonly System.Threading.ReaderWriterLock errorFileLock =
new System.Threading.ReaderWriterLock();
/// <summary>
/// 一个静态方法,用来把一个异常信息记录下来
/// </summary>
/// <param name="e"></param>
public static void LogError( Exception e )
{
LogError( e, string.Empty );
}
/// <summary>
/// 通过错误消息,引发错误的原始异常来持久化一个错误,这里时挖掘错误详细信息的地方,
/// 这里调用了MonitorUtilities工具函数的一些功能获取发生错误的堆栈等,以及遍历原始异常的内部异常,
/// 取出引发异常的类,方法等来获取发生错误时足够多的信息,并把它持久化
/// </summary>
/// <param name="e"></param>
/// <param name="rootMessage"></param>
public static void LogError( Exception e, string rootMessage )
{
GWTrace.EnteringMethod( MethodBase.GetCurrentMethod() );
rootMessage = ( rootMessage == null ? string.Empty : rootMessage.Trim() );
Exception originalException = e;
System.Text.StringBuilder buffer = new System.Text.StringBuilder(4096);
if ( rootMessage.Length > 0 )
buffer.AppendFormat("<font color='RED' size=2><b>{0}</b></font><br/>",
rootMessage );
while (e != null )
{
buffer.AppendFormat("<font color='RED' size=2><b>{0}</b></font><br/>", e.Message );
if (e.TargetSite != null )
{
buffer.Append("<font size=1>");
buffer.AppendFormat( "at method {0}.{1}()<br/>", e.TargetSite.DeclaringType.Name, e.TargetSite.Name );
}
e = e.InnerException;
}
e = originalException;
buffer.Append("<br><font size=2 color=red><b>Stack Trace:</b></font><br/>\n");
buffer.Append("<font size=1>\n");
buffer.Append(MonitorUtilities.ExpandStackTrace(e).Replace("\n", "<br>\n"));
buffer.Append("</font>");
appendMessageToErrorLogFile( buffer.ToString() );
}
/// <summary>
/// 通过错误信息,,错误参数来持久化一条消息,这个重载的方法通常用来记录一条人为的信息
/// 比如说谁在什么时候执行了一个什么操作,
/// </summary>
/// <param name="message"></param>
/// <param name="arrParams"></param>
public static void LogError( string message, params Object[] arrParams )
{
message = ( message == null ? string.Empty : message.Trim() );
message = MonitorUtilities.SafeFormat( message, arrParams );
appendMessageToErrorLogFile( message );
}
/// <summary>
/// 这个是把错误状态持久化的真正的地方,使用System.IO下的几个类,把传进来的信息保存在文本文件里
/// 这里调用私有函数getAppErrorLogFileName()来获取错误日志文件的位置,下面的英文注释可能是说权限之类
/// 的问题吧,你设置的存放文本日志的地方要让给ASPNET用户有写的权限.因为这是个可能引发异常的方法,所以
/// 要做一些异常处理.System.IO里的几个类都比较熟悉了,就不在多注释了哦
/// </summary>
/// <param name="errorMessage"></param>
private static void appendMessageToErrorLogFile( string errorMessage )
{
// Note that if the ASPNET account does not have write privileges
// in the directory that you are planning on storing the file-based
// error log, that file will never be created.
System.IO.StreamWriter errLog = null;
errorFileLock.AcquireWriterLock(10000);
try
{
errLog = System.IO.File.AppendText( getAppErrorLogFileName() );
errLog.WriteLine("<span style='font-family:Verdana'><font size=2>");
errLog.WriteLine("<br/><hr/>\n");
errLog.WriteLine("The following error occurred in the application on {0}", System.DateTime.Now);
errLog.WriteLine("<hr/>\n");
errLog.WriteLine( errorMessage );
errLog.Flush();
errLog.Close();
}
catch (Exception ex)
{
GWTrace.Trace(
TraceLevel.Error, "An error occurred when saving an error to disk: {0}", ex.ToString() );
}
finally
{
errorFileLock.ReleaseLock();
try
{
if (errLog != null )
{
errLog.Flush();
errLog.Close();
}
}
catch { }
}
}
/// <summary>
/// 获取存放文本日志的位置,先从web.config里后去,如果设置的目录没有的话就创建一个目录,如果创建不成功的话
/// 就默认到C盘跟目录下写日志,一般系统最少有一个主分区,也就是说一般都会有个C盘,所以C盘很保险,这里也是考虑
/// 了多种情况,最终保证日志尽量能持久下来,这里是在指定的目录里,根据错误生成的时间来创建一个文本文件,以便
/// 以后方便分类按日期查看.这个方法里调用了私有静态方法checkAndCreateDir,接下来咱们就来看这个方法
/// </summary>
/// <returns></returns>
private static string getAppErrorLogFileName()
{
string errorLogBaseDir = System.Configuration.ConfigurationSettings.AppSettings["ErrorLogBaseDir"];
string errorLogDir = checkAndCreateDir( errorLogBaseDir, "C:\\" );
string errorFileName = string.Format(
"Error-{0}.htm",
System.DateTime.Now.ToString("yyyyMMMdd"));
return errorLogDir + errorFileName;
}
/// <summary>
/// 从web.config里获取保存错误日志的目录,如果没有就创建,如果创建不了就返回一个默认的目录
/// </summary>
/// <param name="newDir">要检查的目录</param>
/// <param name="fallBackDir">默认目录</param>
/// <returns>最终返回的目录</returns>
private static string checkAndCreateDir( string newDir, string fallBackDir )
{
GWTrace.EnteringMethod( MethodBase.GetCurrentMethod() );
if (System.IO.Directory.Exists( newDir ) ) return newDir;
try
{
System.IO.Directory.CreateDirectory( newDir );
if (System.IO.Directory.Exists( newDir ) )
return newDir;
else
return fallBackDir;
}
catch (Exception ex )
{
GWTrace.Trace( TraceLevel.Error,
"There was an error creating the directory {0} : {1}",
newDir,
ex.ToString() );
return fallBackDir;
}
}
}
}
* Class : FileErrorLog
* Namespace : GW.MonitorServices.Logging
* Assembly : GW.MonitorServices.Logging
* Author : Kevin Hoffman
* Description : Class responsible for logging error information to HTML text files as backup/alternate to DB error logging.
*/
using System;
using System.Configuration;
using System.Diagnostics;
using System.Reflection;
namespace GW.MonitorServices.Logging
{
/// <summary>
/// 把错误持久到文本文件的类,这个类用来把错误信息或指定信息记录在一个文本文件里,并
/// 使用HTML格式,方便你查看
/// </summary>
public class FileErrorLog
{
/// <summary>
/// 设置一个读写锁,防治在操作日志文本文件的时候别人也使用,这样就不会出现并发问题
/// </summary>
private static readonly System.Threading.ReaderWriterLock errorFileLock =
new System.Threading.ReaderWriterLock();
/// <summary>
/// 一个静态方法,用来把一个异常信息记录下来
/// </summary>
/// <param name="e"></param>
public static void LogError( Exception e )
{
LogError( e, string.Empty );
}
/// <summary>
/// 通过错误消息,引发错误的原始异常来持久化一个错误,这里时挖掘错误详细信息的地方,
/// 这里调用了MonitorUtilities工具函数的一些功能获取发生错误的堆栈等,以及遍历原始异常的内部异常,
/// 取出引发异常的类,方法等来获取发生错误时足够多的信息,并把它持久化
/// </summary>
/// <param name="e"></param>
/// <param name="rootMessage"></param>
public static void LogError( Exception e, string rootMessage )
{
GWTrace.EnteringMethod( MethodBase.GetCurrentMethod() );
rootMessage = ( rootMessage == null ? string.Empty : rootMessage.Trim() );
Exception originalException = e;
System.Text.StringBuilder buffer = new System.Text.StringBuilder(4096);
if ( rootMessage.Length > 0 )
buffer.AppendFormat("<font color='RED' size=2><b>{0}</b></font><br/>",
rootMessage );
while (e != null )
{
buffer.AppendFormat("<font color='RED' size=2><b>{0}</b></font><br/>", e.Message );
if (e.TargetSite != null )
{
buffer.Append("<font size=1>");
buffer.AppendFormat( "at method {0}.{1}()<br/>", e.TargetSite.DeclaringType.Name, e.TargetSite.Name );
}
e = e.InnerException;
}
e = originalException;
buffer.Append("<br><font size=2 color=red><b>Stack Trace:</b></font><br/>\n");
buffer.Append("<font size=1>\n");
buffer.Append(MonitorUtilities.ExpandStackTrace(e).Replace("\n", "<br>\n"));
buffer.Append("</font>");
appendMessageToErrorLogFile( buffer.ToString() );
}
/// <summary>
/// 通过错误信息,,错误参数来持久化一条消息,这个重载的方法通常用来记录一条人为的信息
/// 比如说谁在什么时候执行了一个什么操作,
/// </summary>
/// <param name="message"></param>
/// <param name="arrParams"></param>
public static void LogError( string message, params Object[] arrParams )
{
message = ( message == null ? string.Empty : message.Trim() );
message = MonitorUtilities.SafeFormat( message, arrParams );
appendMessageToErrorLogFile( message );
}
/// <summary>
/// 这个是把错误状态持久化的真正的地方,使用System.IO下的几个类,把传进来的信息保存在文本文件里
/// 这里调用私有函数getAppErrorLogFileName()来获取错误日志文件的位置,下面的英文注释可能是说权限之类
/// 的问题吧,你设置的存放文本日志的地方要让给ASPNET用户有写的权限.因为这是个可能引发异常的方法,所以
/// 要做一些异常处理.System.IO里的几个类都比较熟悉了,就不在多注释了哦
/// </summary>
/// <param name="errorMessage"></param>
private static void appendMessageToErrorLogFile( string errorMessage )
{
// Note that if the ASPNET account does not have write privileges
// in the directory that you are planning on storing the file-based
// error log, that file will never be created.
System.IO.StreamWriter errLog = null;
errorFileLock.AcquireWriterLock(10000);
try
{
errLog = System.IO.File.AppendText( getAppErrorLogFileName() );
errLog.WriteLine("<span style='font-family:Verdana'><font size=2>");
errLog.WriteLine("<br/><hr/>\n");
errLog.WriteLine("The following error occurred in the application on {0}", System.DateTime.Now);
errLog.WriteLine("<hr/>\n");
errLog.WriteLine( errorMessage );
errLog.Flush();
errLog.Close();
}
catch (Exception ex)
{
GWTrace.Trace(
TraceLevel.Error, "An error occurred when saving an error to disk: {0}", ex.ToString() );
}
finally
{
errorFileLock.ReleaseLock();
try
{
if (errLog != null )
{
errLog.Flush();
errLog.Close();
}
}
catch { }
}
}
/// <summary>
/// 获取存放文本日志的位置,先从web.config里后去,如果设置的目录没有的话就创建一个目录,如果创建不成功的话
/// 就默认到C盘跟目录下写日志,一般系统最少有一个主分区,也就是说一般都会有个C盘,所以C盘很保险,这里也是考虑
/// 了多种情况,最终保证日志尽量能持久下来,这里是在指定的目录里,根据错误生成的时间来创建一个文本文件,以便
/// 以后方便分类按日期查看.这个方法里调用了私有静态方法checkAndCreateDir,接下来咱们就来看这个方法
/// </summary>
/// <returns></returns>
private static string getAppErrorLogFileName()
{
string errorLogBaseDir = System.Configuration.ConfigurationSettings.AppSettings["ErrorLogBaseDir"];
string errorLogDir = checkAndCreateDir( errorLogBaseDir, "C:\\" );
string errorFileName = string.Format(
"Error-{0}.htm",
System.DateTime.Now.ToString("yyyyMMMdd"));
return errorLogDir + errorFileName;
}
/// <summary>
/// 从web.config里获取保存错误日志的目录,如果没有就创建,如果创建不了就返回一个默认的目录
/// </summary>
/// <param name="newDir">要检查的目录</param>
/// <param name="fallBackDir">默认目录</param>
/// <returns>最终返回的目录</returns>
private static string checkAndCreateDir( string newDir, string fallBackDir )
{
GWTrace.EnteringMethod( MethodBase.GetCurrentMethod() );
if (System.IO.Directory.Exists( newDir ) ) return newDir;
try
{
System.IO.Directory.CreateDirectory( newDir );
if (System.IO.Directory.Exists( newDir ) )
return newDir;
else
return fallBackDir;
}
catch (Exception ex )
{
GWTrace.Trace( TraceLevel.Error,
"There was an error creating the directory {0} : {1}",
newDir,
ex.ToString() );
return fallBackDir;
}
}
}
}
/*
* Class : DbErrorLog
* Namespace : GW.MonitorServices.Logging
* Assembly : GW.MonitorServices.Logging
* Author : Kevin Hoffman
* Description : Class that is responsible for logging system errors to the database.
*/
using System;
using System.Text;
using System.Reflection;
using System.Diagnostics;
using GW.CMPServices;
using GW.MonitorServices;
namespace GW.MonitorServices.Logging
{
/// <summary>
/// 这个类用来把错误状态保存到数据库里,一会儿我把保存错误的表结构发给大家哦
/// </summary>
public class DbErrorLog
{
//防治实例化本垒
private DbErrorLog() { }
/// <summary>
/// 记录异常
/// </summary>
/// <param name="e">要记录的异常</param>
/// <returns>返回的异常编号</returns>
public static long LogError( Exception e )
{
return LogError( e, string.Empty );
}
/// <summary>
/// 重载的方法,根据原始异常和错误信息把这些信息记录到数据库里,这里使用的不是普通的SqlHelper方式来保存数据库
/// 而是用一种托管容器持久性的方法来完成的,也就是CMP模式,如果你看不懂,你可以修改成你能看懂的方式,但是要引入相关的
/// System.Data.SqlClient等空间,不过以后我有空会给大家介绍在.NET里如何实现EJB里的CMP模式的.
/// </summary>
/// <param name="e">原始异常</param>
/// <param name="rootMessage">错误消息</param>
/// <returns>返回错误号</returns>
public static long LogError( Exception e, string rootMessage )
{
//跟踪输出本方法
GWTrace.EnteringMethod( MethodBase.GetCurrentMethod() );
//创建一个字符串缓存类,用来保存一些错误状态的相信信息,一会儿就要把他们保存到数据库里
StringBuilder buffer = new StringBuilder(2048);
try
{
if (rootMessage.Length > 0)
buffer.AppendFormat( "{0}\n\n", rootMessage ); //原始错误信息
buffer.Append( MonitorUtilities.ExpandStackTrace( e ) );//发生错误的堆栈
DbErrorEntry dbEntry = new DbErrorEntry(); //创建一个错误记录实体,一会儿我就贴它的源码
dbEntry.ErrorMessage = buffer.ToString(); //设置错误信息
dbEntry.ExtendedInfo = MonitorUtilities.GetProcessInfo();//设置扩展信息
dbEntry.ServerName = MonitorUtilities.GetMachineName(); //设置发生错误的机器
SqlPersistenceContainer sqlPC = new SqlPersistenceContainer(
CMPServices.CMPConfigurationHandler.ContainerMaps["ERROR_LOG"] ); //创建一个托管的容器
//执行容器的Insert方法,并把刚才创建的促无实体做为参数,要保证这一步成功要做一些额外的设置,在web.config里
//设置元数据,最后再给大家介绍,容器只执行CRUD这些标准操作,如果你想让一个容器不支持某个操作,需要重写它的那些
//标准操作,并引发异常,下次有机会再详细阐述,关于ORM,CMP的详细内容太复杂,而且争议也很大,这里不多唠叨了.
sqlPC.Insert( dbEntry );
return dbEntry.ErrorId;
}
catch (Exception ex )
{
//这里一定要把异常抛出去,因为一般不直接调用这个类来持久化错误,它一般由ErrorLog类来调用
//所以这里有错误要向外层抛出,否则外面就接不到了,也就无法处理了,对吧.
// this must be thrown so the generic log front-end can
// tell that there was a db error log failure and write the
// error to a disk file instead.
GWTrace.Trace( TraceLevel.Error, "LogError Failed [{0}]", ex.ToString() );
throw new Exception("Database log failure", ex );
}
}
}
}
* Class : DbErrorLog
* Namespace : GW.MonitorServices.Logging
* Assembly : GW.MonitorServices.Logging
* Author : Kevin Hoffman
* Description : Class that is responsible for logging system errors to the database.
*/
using System;
using System.Text;
using System.Reflection;
using System.Diagnostics;
using GW.CMPServices;
using GW.MonitorServices;
namespace GW.MonitorServices.Logging
{
/// <summary>
/// 这个类用来把错误状态保存到数据库里,一会儿我把保存错误的表结构发给大家哦
/// </summary>
public class DbErrorLog
{
//防治实例化本垒
private DbErrorLog() { }
/// <summary>
/// 记录异常
/// </summary>
/// <param name="e">要记录的异常</param>
/// <returns>返回的异常编号</returns>
public static long LogError( Exception e )
{
return LogError( e, string.Empty );
}
/// <summary>
/// 重载的方法,根据原始异常和错误信息把这些信息记录到数据库里,这里使用的不是普通的SqlHelper方式来保存数据库
/// 而是用一种托管容器持久性的方法来完成的,也就是CMP模式,如果你看不懂,你可以修改成你能看懂的方式,但是要引入相关的
/// System.Data.SqlClient等空间,不过以后我有空会给大家介绍在.NET里如何实现EJB里的CMP模式的.
/// </summary>
/// <param name="e">原始异常</param>
/// <param name="rootMessage">错误消息</param>
/// <returns>返回错误号</returns>
public static long LogError( Exception e, string rootMessage )
{
//跟踪输出本方法
GWTrace.EnteringMethod( MethodBase.GetCurrentMethod() );
//创建一个字符串缓存类,用来保存一些错误状态的相信信息,一会儿就要把他们保存到数据库里
StringBuilder buffer = new StringBuilder(2048);
try
{
if (rootMessage.Length > 0)
buffer.AppendFormat( "{0}\n\n", rootMessage ); //原始错误信息
buffer.Append( MonitorUtilities.ExpandStackTrace( e ) );//发生错误的堆栈
DbErrorEntry dbEntry = new DbErrorEntry(); //创建一个错误记录实体,一会儿我就贴它的源码
dbEntry.ErrorMessage = buffer.ToString(); //设置错误信息
dbEntry.ExtendedInfo = MonitorUtilities.GetProcessInfo();//设置扩展信息
dbEntry.ServerName = MonitorUtilities.GetMachineName(); //设置发生错误的机器
SqlPersistenceContainer sqlPC = new SqlPersistenceContainer(
CMPServices.CMPConfigurationHandler.ContainerMaps["ERROR_LOG"] ); //创建一个托管的容器
//执行容器的Insert方法,并把刚才创建的促无实体做为参数,要保证这一步成功要做一些额外的设置,在web.config里
//设置元数据,最后再给大家介绍,容器只执行CRUD这些标准操作,如果你想让一个容器不支持某个操作,需要重写它的那些
//标准操作,并引发异常,下次有机会再详细阐述,关于ORM,CMP的详细内容太复杂,而且争议也很大,这里不多唠叨了.
sqlPC.Insert( dbEntry );
return dbEntry.ErrorId;
}
catch (Exception ex )
{
//这里一定要把异常抛出去,因为一般不直接调用这个类来持久化错误,它一般由ErrorLog类来调用
//所以这里有错误要向外层抛出,否则外面就接不到了,也就无法处理了,对吧.
// this must be thrown so the generic log front-end can
// tell that there was a db error log failure and write the
// error to a disk file instead.
GWTrace.Trace( TraceLevel.Error, "LogError Failed [{0}]", ex.ToString() );
throw new Exception("Database log failure", ex );
}
}
}
}
/*
* Class : ErrorLog
* Namespace : GW.MonitorServices.Logging
* Assembly : GW.MonitorServices.Logging
* Author : Kevin Hoffman
* Description : Class for handling all forms of error logging.
*/
using System;
using System.Configuration;
using System.Reflection;
using System.Diagnostics;
namespace GW.MonitorServices.Logging
{
/// <summary>
/// 错误日志类,本来来把程序运行中出现的错误持久化,方便以后分析,先视图把它放在数据库里,
/// 并在一个文本文件里做个标记,如果在把错误持久到数据库的过程中遇到了错误,就把信息保存在一个
/// html文件里,这样只要有错误发生始终会持久在一个安全的地方,方便你做错误分析,嘿嘿.
/// </summary>
public class ErrorLog
{
/// <summary>
/// 错误日志标志的文件目录
/// </summary>
private static string errorUrlPrefix;
/// <summary>
/// 只传入异常的构造函数,返回一个长整型的错误号
/// </summary>
/// <param name="appError">异常</param>
/// <returns>返回错误号</returns>
public static long LogError( Exception appError )
{
return LogError( appError, string.Empty );
}
/// <summary>
/// 根据原始异常和错误信息来持久化错误状态
/// </summary>
/// <param name="appError">引发错误的异常</param>
/// <param name="rootMessage">自定义信息</param>
/// <returns></returns>
public static long LogError( Exception appError, string rootMessage )
{
//跟踪输出这个方法
GWTrace.EnteringMethod( MethodBase.GetCurrentMethod() );
rootMessage = ( rootMessage == null ? string.Empty : rootMessage.Trim() );
//试图把错误信息持久到数据库里,并在一个文本文件里做个标志,提示有个错误发生,已经把它持久到数据库里了,你去看看
//如果不能就把它持久到数据库里就执行catch后面的语句,把它试图持久到一个文本文件里
try
{
long errorId = DbErrorLog.LogError( appError, rootMessage );
FileErrorLog.LogError( GWException.GetGWExceptionMessage( GWExceptionMessages.SeeDatabase ),
ErrorViewUrlPrefix, errorId );
return errorId;
}
catch (Exception dbError )
{
//跟踪输出一条信息,就说是在往数据库里写错误的时候失败了.
GWTrace.Trace( TraceLevel.Error, "DB Error Log Attempt Failed" );
try
{
//把错误记录到错误日志文件里去
FileErrorLog.LogError( appError, rootMessage );
//在错误标志文件里记录一条,数据库持久错误的消息,因为如果执行到这里,肯定是在把错误保存到数据库的时候
//失败了,对吧,这时候还要返回一个错误码,以便让调用程序知道这个方法到底执行了哪一步,这也是一个小技巧
FileErrorLog.LogError( dbError, GWException.GetGWExceptionMessage( GWExceptionMessages.DbLogFailed ) );
return -1;
}
catch
{
//如果都无法持久错误,哪只好跟踪输出一条错误信息了,就说在持久错误状态的时候失败了,一般这时候就是有严重错误了
//最好在这里给管理员发封电子邮件,那些东西你自己扩展吧,你发条儿短信都行.
GWTrace.Trace( TraceLevel.Error, "Backup File Error Log Attempt Failed");
return -2;
}
}
}
/// <summary>
/// 错误标志文件的目录,错误发生的时候无论是把相信信息记录到数据库里了,还是记录到错误日志文本文件里了
/// 都会在一个错误标志文件里记录一条,表示发生了一条错误,你想查看具体错误就去数据库和去保存错误日志的目录
/// 里去看吧,就这个意思,所以你每天检查错误标志文件就行了.默认位置是/GadgetsWarehouse/ErrorLog/这里,当然
/// 你可以在web.config里设置,我不会翻译ErrorViewUrlPrefix这是什么意思哦,先把它翻译成错误标志文件目录吧
/// </summary>
private static string ErrorViewUrlPrefix
{
get
{
if ( errorUrlPrefix != null) return errorUrlPrefix;
string prefix = ConfigurationSettings.AppSettings["ErrorViewUrlPrefix"];
prefix = ( prefix == null ? string.Empty : prefix.Trim() );
if (prefix.Length == 0 )
prefix = "/GadgetsWarehouse/ErrorLog/";
errorUrlPrefix = prefix;
return errorUrlPrefix;
}
}
}
}
* Class : ErrorLog
* Namespace : GW.MonitorServices.Logging
* Assembly : GW.MonitorServices.Logging
* Author : Kevin Hoffman
* Description : Class for handling all forms of error logging.
*/
using System;
using System.Configuration;
using System.Reflection;
using System.Diagnostics;
namespace GW.MonitorServices.Logging
{
/// <summary>
/// 错误日志类,本来来把程序运行中出现的错误持久化,方便以后分析,先视图把它放在数据库里,
/// 并在一个文本文件里做个标记,如果在把错误持久到数据库的过程中遇到了错误,就把信息保存在一个
/// html文件里,这样只要有错误发生始终会持久在一个安全的地方,方便你做错误分析,嘿嘿.
/// </summary>
public class ErrorLog
{
/// <summary>
/// 错误日志标志的文件目录
/// </summary>
private static string errorUrlPrefix;
/// <summary>
/// 只传入异常的构造函数,返回一个长整型的错误号
/// </summary>
/// <param name="appError">异常</param>
/// <returns>返回错误号</returns>
public static long LogError( Exception appError )
{
return LogError( appError, string.Empty );
}
/// <summary>
/// 根据原始异常和错误信息来持久化错误状态
/// </summary>
/// <param name="appError">引发错误的异常</param>
/// <param name="rootMessage">自定义信息</param>
/// <returns></returns>
public static long LogError( Exception appError, string rootMessage )
{
//跟踪输出这个方法
GWTrace.EnteringMethod( MethodBase.GetCurrentMethod() );
rootMessage = ( rootMessage == null ? string.Empty : rootMessage.Trim() );
//试图把错误信息持久到数据库里,并在一个文本文件里做个标志,提示有个错误发生,已经把它持久到数据库里了,你去看看
//如果不能就把它持久到数据库里就执行catch后面的语句,把它试图持久到一个文本文件里
try
{
long errorId = DbErrorLog.LogError( appError, rootMessage );
FileErrorLog.LogError( GWException.GetGWExceptionMessage( GWExceptionMessages.SeeDatabase ),
ErrorViewUrlPrefix, errorId );
return errorId;
}
catch (Exception dbError )
{
//跟踪输出一条信息,就说是在往数据库里写错误的时候失败了.
GWTrace.Trace( TraceLevel.Error, "DB Error Log Attempt Failed" );
try
{
//把错误记录到错误日志文件里去
FileErrorLog.LogError( appError, rootMessage );
//在错误标志文件里记录一条,数据库持久错误的消息,因为如果执行到这里,肯定是在把错误保存到数据库的时候
//失败了,对吧,这时候还要返回一个错误码,以便让调用程序知道这个方法到底执行了哪一步,这也是一个小技巧
FileErrorLog.LogError( dbError, GWException.GetGWExceptionMessage( GWExceptionMessages.DbLogFailed ) );
return -1;
}
catch
{
//如果都无法持久错误,哪只好跟踪输出一条错误信息了,就说在持久错误状态的时候失败了,一般这时候就是有严重错误了
//最好在这里给管理员发封电子邮件,那些东西你自己扩展吧,你发条儿短信都行.
GWTrace.Trace( TraceLevel.Error, "Backup File Error Log Attempt Failed");
return -2;
}
}
}
/// <summary>
/// 错误标志文件的目录,错误发生的时候无论是把相信信息记录到数据库里了,还是记录到错误日志文本文件里了
/// 都会在一个错误标志文件里记录一条,表示发生了一条错误,你想查看具体错误就去数据库和去保存错误日志的目录
/// 里去看吧,就这个意思,所以你每天检查错误标志文件就行了.默认位置是/GadgetsWarehouse/ErrorLog/这里,当然
/// 你可以在web.config里设置,我不会翻译ErrorViewUrlPrefix这是什么意思哦,先把它翻译成错误标志文件目录吧
/// </summary>
private static string ErrorViewUrlPrefix
{
get
{
if ( errorUrlPrefix != null) return errorUrlPrefix;
string prefix = ConfigurationSettings.AppSettings["ErrorViewUrlPrefix"];
prefix = ( prefix == null ? string.Empty : prefix.Trim() );
if (prefix.Length == 0 )
prefix = "/GadgetsWarehouse/ErrorLog/";
errorUrlPrefix = prefix;
return errorUrlPrefix;
}
}
}
}