记录到日志中的异常栈缺失

时间:2014-10-28 13:45:01   收藏:0   阅读:120

项目中有这样一个场景:

使用反射处理所有业务调用,在反射调用点使用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         }

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!