标签:style blog io color 使用 sp div on 问题
项目中有这样一个场景:
使用反射处理所有业务调用,在反射调用点使用try-catch集中处理异常,并将异常信息记录到日志。其中日志记录是异步的。
问题:
记录到日志中的异常的StackTrace和有时候和Debug时抛出的异常的StackTrace不一样。
原因:
由于记录日志是异步的,如果记录日志发生在throw之前,记录到日志中的异常的StackTrace就是正确的(异常真正发生点到throw点的所有StackTrace);如果记录日志发生在throw之后,记录到日志中的异常的StackTrace就是不正确的(只有当前throw点到代码入口点的StackTrace);
因为抛出的异常(或是该异常的引用)刚好是用来记录日志用的异常实例,且throw动作会对抛出的异常(和记录日志的异常实例是同一个引用)重新生成StackTrace,所以记录日志用的异常的StackTrace被重新生成了。
(备注1:StackTrace是Exception的只读属性,throw时会对扔出的异常生成StackTrace)
(备注2:如果记录日志是同步的且先记录日志后throw,则应该不会发生这个问题)
解决方案:
♦用到的方法:
1 // 深赋值异常链上的所有异常,但是会丢失异常链上非叶子节点的异常的StackTrace。最内部的异常信息会完整保留,因为最内部的异常不是副本 2 public static Exception CloneInnerExceptionRecursive(Exception ex) 3 { 4 Exception exception = null; 5 6 if (ex.InnerException == null) 7 { 8 exception = ex; 9 } 10 else 11 { 12 Stack<Exception> stack = new Stack<Exception>(); 13 stack.Push(ex); 14 Exception innerException = ex.InnerException; 15 while (innerException != null) 16 { 17 if (innerException.InnerException == null) 18 { 19 break; 20 } 21 stack.Push(innerException); 22 innerException = innerException.InnerException; 23 } 24 25 try 26 { 27 Exception chain = innerException; 28 Exception temp = null; 29 while (stack.Count > 0) 30 { 31 temp = stack.Pop(); 32 chain = CloneException(temp, chain); 33 } 34 exception = chain; 35 } 36 catch 37 { 38 } 39 40 if (exception == null || exception.InnerException == null) 41 { 42 exception = ex.InnerException; 43 } 44 } 45 46 return exception; 47 }
1 // 复制异常 2 public static Exception CloneException(Exception ex, Exception inner) 3 { 4 return (Exception)ex.GetType().GetConstructor(new Type[] { typeof(string), typeof(Exception) }).Invoke(new object[] { ex.Message, inner }); 5 }
标签:style blog io color 使用 sp div on 问题
原文地址:http://www.cnblogs.com/royliugc/p/4056483.html