有了以上这些基本素材之后,便是要考虑发布器的核心了,如何分析异常、匹配异常,然后得到新的异常记录并将它发布出去,这个类的名字叫ExceptionManager,我不罗列整个类的全部代码,只对其中一些核心代码进行说明:
当一个异常进入发布器中进行处理的时候,首先会根据当前语言取得相应语言的异常匹配资料,如果没有,则取得后备匹配资料:
ExceptionDetailData exceptionDetailDS = LogAccess.GetExceptionDetail();
ExceptionDetailData.ExceptionDetailRow[] exceptionDetials = (ExceptionDetailData.ExceptionDetailRow[])exceptionDetailDS.ExceptionDetail.Select("Language = '" +language+ "'");
if (exceptionDetials.Length == 0)
{
exceptionDetials = (ExceptionDetailData.ExceptionDetailRow[])exceptionDetailDS.ExceptionDetail.Select("Language IS NULL");
}
然后分析异常,取出有关属性放入相应的字段中:
string exceptionType = ee.GetType().ToString().Trim();
string inMessage ="";
string outMessage ="";
string source = "";
string stackTrace = "";
string targetSite = "";
string helpLink = "";
string eventLever = "";
userHelpLink = "";
#region 分析异常属性
if (ee.Message != null)
{
inMessage = ee.Message.Trim();
}
if (ee.HelpLink != null)
{
helpLink = ee.HelpLink.Trim();
}
if (ee.Source != null)
{
source = ee.Source.Trim();
}
if ( ee.StackTrace != null)
{
stackTrace = ee.StackTrace.Trim();
}
if (ee.TargetSite != null)
{
targetSite = ee.TargetSite.ToString().Trim();
}
#endregion
接着,匹配异常资料,为了要实现结构化的查询,这里使用的是一个比较笨的算法,毕竟,我觉得这里的技巧并不是太重要:
#region 查询异常处理
bool find = false;
foreach (ExceptionDetailData.ExceptionDetailRow exceptionDetail in exceptionDetials)
{
if (exceptionDetail.Type.Trim().ToLower() == exceptionType.ToLower() && !exceptionDetail.IsInMessage1Null() && !exceptionDetail.IsInMessage2Null() && !exceptionDetail.IsInMessage3Null() && !exceptionDetail.IsInMessage4Null())
{
string[] mathString = new string[4];
mathString[0] = exceptionDetail.InMessage1.Trim();
mathString[1] = exceptionDetail.InMessage2.Trim();
mathString[2] = exceptionDetail.InMessage3.Trim();
mathString[3] = exceptionDetail.InMessage4.Trim();
find = MatchMessage(inMessage, mathString);
if(find == true)
{
GetErrorMessage(out userHelpLink,out outMessage,out eventLever, exceptionDetail);
break;
}
}
}
if (find == false)
{
……
这里用到了一个方法MatchMessage,用来判定异常资料是否匹配:
internal static bool MatchMessage(string message, string[] matchMessage)
{
foreach (string match in matchMessage)
{
if( message.ToLower().IndexOf(match.ToLower()) == -1)
{
return false;
}
}
return true;
}
还有另外一个方法,用来获取输出信息:
internal static void GetErrorMessage(out string userHelpLink, out string outMessage,out string eventLever, ExceptionDetailData.ExceptionDetailRow exceptionDetail )
{
outMessage = "";
if (!exceptionDetail.IsHelpLinkNull())
{
userHelpLink = exceptionDetail.HelpLink.Trim();
}
else
{
userHelpLink = "";
}
eventLever = exceptionDetail.EventLevel;
if (!exceptionDetail.IsOutMessageNull())
{
CustomOutMessageData ds = LogAccess.GetCustomOutMessage();
CustomOutMessageData.CustomOutMessageRow customOutMessage = null;
if (ds.CustomOutMessage.FindByLanguage(Thread.CurrentThread.CurrentUICulture.Name) != null)
{
customOutMessage = ds.CustomOutMessage.FindByLanguage(Thread.CurrentThread.CurrentUICulture.Name);
}
else if (ds.CustomOutMessage.FindByLanguage("Default") != null)
{
customOutMessage = ds.CustomOutMessage.FindByLanguage("Default");
}
if (customOutMessage != null)
{
if (exceptionDetail.EventLevel.ToLower() == EventLevel.Error.ToString().ToLower())
outMessage = customOutMessage.ErrorExceptionMessage +":" + exceptionDetail.OutMessage.Trim() +" " +customOutMessage.ErrorPleaseDoSomethingMessage;
else if (exceptionDetail.EventLevel.ToLower() == EventLevel.FailureAudit.ToString().ToLower())
outMessage = customOutMessage.FailureAuditExceptionMessage +":" + exceptionDetail.OutMessage.Trim() +" " +customOutMessage.FailureAuditPleaseDoSomethingMessage;
else if (exceptionDetail.EventLevel.ToLower() == EventLevel.Information.ToString().ToLower())
outMessage = customOutMessage.InformationExceptionMessage +":" + exceptionDetail.OutMessage.Trim() +" " +customOutMessage.InformationPleaseDoSomethingMessage;
else if (exceptionDetail.EventLevel.ToLower() == EventLevel.SuccessAudit.ToString().ToLower())
outMessage = customOutMessage.SuccessAuditExceptionMessage +":" + exceptionDetail.OutMessage.Trim() +" " +customOutMessage.SuccessAuditPleaseDoSomethingMessage;
else if (exceptionDetail.EventLevel.ToLower() == EventLevel.Warning.ToString().ToLower())
outMessage = customOutMessage.WarningExceptionMessage +":" + exceptionDetail.OutMessage.Trim() +" " +customOutMessage.WarningPleaseDoSomethingMessage;
}
else
{
outMessage = exceptionDetail.OutMessage.Trim();
}
}
}
这里便实现了输出信息的本地化,根据当前语言输出的信息头、友好信息,等等。
现在得到了这些输出信息后,便是要将其记入日志了,下面两个方法便分别向系统日志和XML文件写入日志:
向系统日志写入日志:
private static void PublishToSystemLog(ExceptionLogData.ExceptionLogRow exceptionLog)
{
if (!EventLog.SourceExists(AppConfig.ApplicationName))
{
EventLog.CreateEventSource(AppConfig.ApplicationName,"Storm");
}
EventLog eventLog = new EventLog();
eventLog.Source = AppConfig.ApplicationName;
string message = "";
CustomOutMessageData ds = LogAccess.GetCustomOutMessage();
CustomOutMessageData.CustomOutMessageRow customOutMessage;
if (ds.CustomOutMessage.FindByLanguage(Thread.CurrentThread.CurrentUICulture.Name) != null)
{
customOutMessage = ds.CustomOutMessage.FindByLanguage(Thread.CurrentThread.CurrentUICulture.Name);
}
else if (ds.CustomOutMessage.FindByLanguage("Default") != null)
{
customOutMessage = ds.CustomOutMessage.FindByLanguage("Default");
}
else
{
customOutMessage = null;
}
string eventLever = exceptionLog.EventLevel.ToLower();
EventLogEntryType logType = EventLogEntryType.Error;
if (eventLever == EventLogEntryType.Error.ToString().ToLower())
{
logType = EventLogEntryType.Error;
}
else if (eventLever == EventLogEntryType.FailureAudit.ToString().ToLower())
{
logType = EventLogEntryType.FailureAudit;
}
else if (eventLever == EventLogEntryType.Information.ToString().ToLower())
{
logType = EventLogEntryType.Information;
}
else if (eventLever == EventLogEntryType.SuccessAudit.ToString().ToLower())
{
logType = EventLogEntryType.SuccessAudit;
}
else if (eventLever == EventLogEntryType.Warning.ToString().ToLower())
{
logType = EventLogEntryType.Warning;
}
if (customOutMessage != null)
{
message += (customOutMessage.LogTimeHeader + ":" +(exceptionLog.IsLogTimeNull()?"":exceptionLog.LogTime.ToString("yyyy-MM-dd HH:mm:ss")) +"\n");
message += (customOutMessage.ExceptionTypeHeader + ":" + (exceptionLog.IsExceptionTypeNull()?"":exceptionLog.ExceptionType) + "\n");
message += (customOutMessage.ExceptiomOriginalMessageHeader + ":" + (exceptionLog.IsExceptiomOriginalMessageNull()?"":exceptionLog.ExceptiomOriginalMessage) +"\n");
message += (customOutMessage.ExceptionSourceHeader + ":" + (exceptionLog.IsExceptionSourceNull()?"":exceptionLog.ExceptionSource) +"\n");
message += (customOutMessage.ExceptionStackTraceHeader + ":" + (exceptionLog.IsExceptionStackTraceNull()?"":exceptionLog.ExceptionStackTrace) +"\n");
message += (customOutMessage.ExceptionTargetSiteHeader + ":" + (exceptionLog.IsExceptionTargetSiteNull()?"":exceptionLog.ExceptionTargetSite) + "\n");
message += (customOutMessage.ExceptionHelpLinkHeader + ":" + (exceptionLog.IsExceptionHelpLinkNull()?"":exceptionLog.ExceptionHelpLink) +"\n");
message += (customOutMessage.CustomMessageHeader + ":" + (exceptionLog.IsCustomMessageNull()?"":exceptionLog.CustomMessage) +"\n");
message += (customOutMessage.CustomHelpLinkHeader + ":" + (exceptionLog.IsCustomHelpLinkNull()?"":exceptionLog.CustomHelpLink) + "\n");
message += (customOutMessage.UserNameHeader + ":" + (exceptionLog.IsUserNameNull()?"":exceptionLog.UserName) + "\n");
message += (customOutMessage.ExceptionInducedPathHeader + ":" + (exceptionLog.IsExceptionInducedPathNull()?"":exceptionLog.ExceptionInducedPath) +"\n");
}
else
{
message += ("LogTime:" +(exceptionLog.IsLogTimeNull()?"":exceptionLog.LogTime.ToString("yyyy-MM-dd HH:mm:ss")) +"\n");
message += ("ExceptionType:" + (exceptionLog.IsExceptionTypeNull()?"":exceptionLog.ExceptionType) + "\n");
message += ("ExceptiomOriginalMessage:" + (exceptionLog.IsExceptiomOriginalMessageNull()?"":exceptionLog.ExceptiomOriginalMessage) +"\n");
message += ("ExceptionSource:" + (exceptionLog.IsExceptionSourceNull()?"":exceptionLog.ExceptionSource) +"\n");
message += ("ExceptionStackTrace:" + (exceptionLog.IsExceptionStackTraceNull()?"":exceptionLog.ExceptionStackTrace) +"\n");
message += ("ExceptionTargetSite:" + (exceptionLog.IsExceptionTargetSiteNull()?"":exceptionLog.ExceptionTargetSite) + "\n");
message += ("ExceptionHelpLink:" + (exceptionLog.IsExceptionHelpLinkNull()?"":exceptionLog.ExceptionHelpLink) +"\n");
message += ("CustomMessage:" + (exceptionLog.IsCustomMessageNull()?"":exceptionLog.CustomMessage) +"\n");
message += ("CustomHelpLink:" + (exceptionLog.IsCustomHelpLinkNull()?"":exceptionLog.CustomHelpLink) + "\n");
message += ("UserName:" + (exceptionLog.IsUserNameNull()?"":exceptionLog.UserName) + "\n");
message += ("ExceptionInducedPath:" + (exceptionLog.IsExceptionInducedPathNull()?"":exceptionLog.ExceptionInducedPath) +"\n");
}
eventLog.WriteEntry(message,logType);
}
将日志写入XML文件:
private static void PublishToXMLFile(ExceptionLogData.ExceptionLogRow exceptionLog)
{
ExceptionLogData ds = LogAccess.ReadLogFile();
ExceptionLogData.ExceptionLogRow log = ds.ExceptionLog.NewExceptionLogRow();
log.Guid = Guid.NewGuid();
log.EventLevel = exceptionLog.EventLevel;
if (!exceptionLog.IsLogTimeNull())
{
log.LogTime = exceptionLog.LogTime;
}
if (!exceptionLog.IsExceptionTypeNull())
{
log.ExceptionType = exceptionLog.ExceptionType;
}
if (!exceptionLog.IsExceptiomOriginalMessageNull())
{
log.ExceptiomOriginalMessage = exceptionLog.ExceptiomOriginalMessage;
}
if (!exceptionLog.IsExceptionSourceNull())
{
log.ExceptionSource = exceptionLog.ExceptionSource;
}
if (!exceptionLog.IsExceptionStackTraceNull())
{
log.ExceptionStackTrace = exceptionLog.ExceptionStackTrace;
}
if (!exceptionLog.IsExceptionTargetSiteNull())
{
log.ExceptionTargetSite = exceptionLog.ExceptionTargetSite;
}
if (!exceptionLog.IsExceptionHelpLinkNull())
{
log.ExceptionHelpLink = exceptionLog.ExceptionHelpLink;
}
if (!exceptionLog.IsCustomMessageNull())
{
log.CustomMessage = exceptionLog.CustomMessage;
}
if (!exceptionLog.IsUserNameNull())
{
log.UserName = exceptionLog.UserName;
}
if (!exceptionLog.IsExceptionInducedPathNull())
{
log.ExceptionInducedPath = exceptionLog.ExceptionInducedPath;
}
if (!exceptionLog.IsCustomHelpLinkNull())
{
log.CustomHelpLink = exceptionLog.CustomHelpLink;
}
ds.ExceptionLog.AddExceptionLogRow(log);
LogAccess.WriteLogFile(ds);
}
有了以上全部这些东西之后,我们来看看如果将它们组织在一起,当系统发生异常时,调用的便是这个方法:
/// <summary>
/// 处理异常并返回错误信息
/// </summary>
/// <param name="ee">要处理的异常</param>
/// <returns>错误信息</returns>
public static string PublishException(Exception ee)
{
string outMessage;
string helpLink;
ExceptionLogData ds = new ExceptionLogData();
ExceptionLogData.ExceptionLogRow exceptionLog = ds.ExceptionLog.NewExceptionLogRow();
outMessage = PublishException(out helpLink,ref exceptionLog,ee);
if (ExceptionSetting.ExceptionLogType == CanUseExceptionLogType.XMLFile)
{
PublishToXMLFile(exceptionLog);
}
else if (ExceptionSetting.ExceptionLogType == CanUseExceptionLogType.SystemLog)
{
PublishToSystemLog(exceptionLog);
}
else if (ExceptionSetting.ExceptionLogType == CanUseExceptionLogType.All)
{
PublishToXMLFile(exceptionLog);
PublishToSystemLog(exceptionLog);
}
return outMessage;
}
这样,我们的异常发布器便开发完成了,我们来看看在系统日志中和XML文件中会分别是什么样的记录:
最后,您可以将您的异常发布器在项目中使用了,适用的时候要注意,必须要授予ASPnet帐户对文章前面提到的三个XML文件以写读写的权限。