我目前正在对Windows服务进行维护,并且在代码中的某些位置存在一些异常处理(例如,来自计时器和其他外部事件的回调):
try {
...
}
catch (Exception ex) {
_logger.Log("Unhandled exception: {0}\r\n{1}", ex.Message, ex.StackTrace);
Environment.FailFast("Fatal error.");
}
记录异常信息有助于排除出错的问题。但是,有时候有趣的信息是内部异常,这使得很难确定问题的根本原因。例如,TypeInitializationException
很难理解。
是否有更好的方法来记录异常信息以进行故障排除?
答案 0 :(得分:7)
是否有更好的方法来记录异常信息以进行故障排除?
是的。不要“聪明”并使用ex.Message
和ex.StackTrace
。只需使用ex.ToString()
即可。它将递归到内部异常(如果需要,可以是多个级别)并显示完整的堆栈跟踪。
try {
...
}
catch (Exception ex) {
_logger.Log("Unhandled exception:\r\n{0}", ex);
Environment.FailFast("Fatal error.");
}
为了提供一个小例子,如果您创建一个在类的静态构造函数中抛出异常的类的实例,那么这就是您所获得的。此异常抛出将包含在TypeInitializationException
。
在:
Unhandled exception: The type initializer for 'SomeClass' threw an exception. at SomeNamespace.SomeClass..ctor() at SomeNamespace.Callback() in c:\ExceptionHandlingDemo.cs:line 34
不是很有帮助。很难确定出了什么问题。
后:
Unhandled exception: System.TypeInitializationException: The type initializer for 'SomeClass' threw an exception. ---> System.ArgumentException: An item with the same key has already been added. at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) at SomeNamespace.SomeClass..cctor() in c:\ExceptionHandlingDemo.cs:line 43 --- End of inner exception stack trace --- at SomeNamespace.SomeClass..ctor() at SomeNamespace.Callback() in c:\ExceptionHandlingDemo.cs:line 34
现在,您可以非常轻松地确定问题的根本原因是字典中的重复键,并将其精确定位到源文件中的第43行。
答案 1 :(得分:0)
我不知道这是否会有所帮助,或者它是否过高,但你知道微软的企业库吗? (http://msdn.microsoft.com/en-us/library/ff648951.aspx)。
其中有一个记录“应用程序块”,它是一个大锤,但最终非常强大/灵活。经历了我想要的设置(它的所有配置驱动),这现在是我构建的exerything的标准。
特别是在例外的情况下,我认为为了获得有意义的信息,我根本不需要做太多的事情。
答案 2 :(得分:0)
我不确定这是否会有所帮助。我编写了这个Utility类来记录异常的所有信息,我使用 Exception.Data 和 Exception.Message 来记录信息
此处分享的内容:https://stackoverflow.com/a/15005319/1060656
public class ExceptionInfoUtil
{
public static string GetAllExceptionInfo(Exception ex)
{
StringBuilder sbexception = new StringBuilder();
int i = 1;
sbexception.Append(GetExceptionInfo(ex, i));
while (ex.InnerException != null)
{
i++;
ex = ex.InnerException;
sbexception.Append(GetExceptionInfo(ex, i));
}
return sbexception.ToString();
}
private static string GetExceptionInfo(Exception ex, int count)
{
StringBuilder sbexception = new StringBuilder();
sbexception.AppendLine(string.Format(""));
sbexception.AppendLine(string.Format(""));
sbexception.AppendLine(string.Format("************************************************"));
sbexception.AppendLine(string.Format("************************************************"));
sbexception.AppendLine(string.Format(" Inner Exception : No.{0} ", count));
sbexception.AppendLine(string.Format("************************************************"));
sbexception.AppendLine(string.Format("=================================================="));
sbexception.AppendLine(string.Format(" Error Message : {0} ", ex.Message));
sbexception.AppendLine(string.Format("=================================================="));
#region Mine Thru data dictionary
try
{
sbexception.AppendLine(string.Format("=================================================="));
sbexception.AppendLine(string.Format(" Data parameters Count at Source :{0}", ex.Data.Count));
sbexception.AppendLine(string.Format("=================================================="));
string skey = string.Empty;
foreach (object key in ex.Data.Keys)
{
try
{
if (key != null)
{
skey = Convert.ToString(key);
sbexception.AppendLine(string.Format(" Key :{0} , Value:{1}", skey, Convert.ToString(ex.Data[key])));
}
else
{
sbexception.AppendLine(string.Format(" Key is null"));
}
}
catch (Exception e1)
{
sbexception.AppendLine(string.Format("** Exception occurred when writting log *** [{0}] ", e1.Message));
}
}
}
catch (Exception ex1)
{
sbexception.AppendLine(string.Format("** Exception occurred when writting log *** [{0}] ", ex1.Message));
}
#endregion
sbexception.AppendLine(string.Format("=================================================="));
sbexception.AppendLine(string.Format(" Source : {0} ", ex.Source));
sbexception.AppendLine(string.Format("=================================================="));
sbexception.AppendLine(string.Format(" StackTrace : {0} ", ex.StackTrace));
sbexception.AppendLine(string.Format("=================================================="));
sbexception.AppendLine(string.Format(" TargetSite : {0} ", ex.TargetSite));
sbexception.AppendLine(string.Format("************************************************"));
sbexception.AppendLine(string.Format(" Finished Writting Exception info :{0} ", count));
sbexception.AppendLine(string.Format("************************************************"));
sbexception.AppendLine(string.Format("************************************************"));
sbexception.AppendLine(string.Format(""));
sbexception.AppendLine(string.Format(""));
return sbexception.ToString();
}
}
以下是使用此实用程序类的示例类
[Serializable]
public class FlatFileItem
{
ArrayList errorlist = new ArrayList();
public FlatFileItem()
{
if (errorlist == null) { errorlist = new ArrayList(); }
}
//Name of the file
public string FileName { get; set; }
public override string ToString()
{
return string.Format(@"FlatFileItem (Unzip FTPLineItem) => FileName:{0}", this.FileName);
}
}
public class someclass {
public void somemethod(){
try{
//Throw exception code
} catch (Exception ex)
{
ex.Data["flatfile"] = Convert.ToString(flatfile); //Using data property
flatfile.HasErrors = true; //not there in above example
flatfile.Parent.AddErrorInfo(ex); //not there in above example
logger.Error(String.Format(ex.Message)); //not there in above example
throw ( new Exception ("yourmsg",ex)); //if you want to do this
}
}
}