使用StackTrace堆栈跟踪记录详细日志(可获取行号)

2014-04-25 22:30 by 螺丝钉想要螺丝帽, 350 阅读, 3 评论, 收藏编辑

  上一篇我们提到使用.NET自带的TraceSource实现简单的日志,具体请看《轻松背后的N+疲惫——系统日志》,这一篇注意想讲的是日志的详细记录,包含请求开始到结束的过程中调用的方法链以及记录日志那一刻的类名,方法名,行号等。

  其实也就是堆栈的跟踪了,微软为我们提供了一个对堆栈跟踪的对象StackTrace,具体信息请看 MSDN-StackTrace类.

  下面是对TraceSourceLogger类的改进:

  1     public sealed class TraceSourceLogger
2 :ILogger
3 {
4
5 TraceSource _source;
6
7 public TraceSourceLogger()
8 {
9 _source = new TraceSource("Bulrush");
10 }
11
12 public void Fatal(string message, params object[] args)
13 {
14 if (String.IsNullOrWhiteSpace(message))
15 return;
16
17 string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
18 TraceStack(TraceEventType.Critical, messageToTrace);
19 }
20
21 public void Fatal(string message, Exception exception, params object[] args)
22 {
23 if (String.IsNullOrWhiteSpace(message) || exception == null)
24 return;
25
26 string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
27 TraceException(TraceEventType.Critical, exception, messageToTrace);
28 }
29
30 public void Infomation(string message, params object[] args)
31 {
32 if (String.IsNullOrWhiteSpace(message))
33 return;
34
35 string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
36 Trace(TraceEventType.Information, messageToTrace);
37 }
38
39 public void Warning(string message, params object[] args)
40 {
41 if (String.IsNullOrWhiteSpace(message))
42 return;
43
44 string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
45 Trace(TraceEventType.Warning, messageToTrace);
46 }
47
48 public void Error(string message, params object[] args)
49 {
50 if (String.IsNullOrWhiteSpace(message))
51 return;
52
53 string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
54 TraceStack(TraceEventType.Error, messageToTrace);
55 }
56
57 public void Error(string message, Exception exception, params object[] args)
58 {
59 if (String.IsNullOrWhiteSpace(message) || exception == null)
60 return;
61
62 string messageToTrace = String.Format(CultureInfo.InvariantCulture, message, args);
63 TraceException(TraceEventType.Error, exception, messageToTrace);
64 }
65
66 void Trace(TraceEventType eventType, string message)
67 {
68 if (_source != null)
69 {
70 try
71 {
72 _source.TraceEvent(eventType, (int)eventType, message);
73 }
74 catch (SecurityException)
75 {
76 //这里处理写入是出现的安全问题,如文件没有写入权限。
77 }
78 }
79 }
80
81 void TraceStack(TraceEventType eventType, string message)
82 {
83 string stackMessage = BuildStackTraceMessage();
84 string messageToTrace = message + Environment.NewLine + Environment.NewLine + stackMessage;
85
86 Trace(eventType, messageToTrace);
87 }
88
89 void TraceException(TraceEventType eventType, Exception ex, string message)
90 {
91 StringBuilder builder = new StringBuilder();
92 builder.AppendFormat("错误信息:{0}", message).AppendLine();
93 builder.AppendFormat("异常信息:{0}", ex.Message).AppendLine();
94 builder.AppendFormat("异常类型:{0}", ex.GetType().Name).AppendLine();
95
96 string stackMessage = BuildStackTraceMessage();
97 builder.Append(stackMessage);
98
99 Trace(eventType, builder.ToString());
100 }
101
102 string BuildStackTraceMessage()
103 {
104 StackTrace trace = new StackTrace(true);
105 return BuildStackTraceMessage(trace);
106 }
107
108 string BuildStackTraceMessage(StackTrace stackTrace)
109 {
110 if (stackTrace != null)
111 {
112 var frameList = stackTrace.GetFrames();
113 var realFrameList = frameList.Where(i => i.GetMethod().DeclaringType != this.GetType() && i.GetFileLineNumber() > 0);
114 if (realFrameList.Any())
115 {
116 StringBuilder builder = new StringBuilder();
117 realFrameList = realFrameList.Reverse();
118 var lastFrame = realFrameList.Last();
119 builder.AppendFormat("源文件:{0}", lastFrame.GetFileName()).AppendLine();
120 builder.AppendFormat("行号:{0}", lastFrame.GetFileLineNumber()).AppendLine();
121 builder.AppendFormat("方法名:{0}", lastFrame.GetMethod().ToString()).AppendLine();
122 builder.AppendLine("堆栈跟踪:");
123 builder.AppendLine("=================================================================");
124
125 MethodBase method;
126 foreach (var frame in realFrameList)
127 {
128 method = frame.GetMethod();
129 builder.AppendFormat("> {0} 类下的第{1}行 {2} 方法", method.DeclaringType.ToString(), frame.GetFileLineNumber(), method.ToString()).AppendLine();
130 }
131 builder.AppendLine("=================================================================");
132 return builder.ToString();
133 }
134 }
135 return "没有堆栈信息";
136 }
137 }

最主要的部分在于BuildStackTraceMessage这个方法

 1     string BuildStackTraceMessage(StackTrace stackTrace)
2 {
3 if (stackTrace != null)
4 {
5 var frameList = stackTrace.GetFrames();
6 var realFrameList = frameList.Where(i => i.GetMethod().DeclaringType != this.GetType() && i.GetFileLineNumber() > 0);
7 if (realFrameList.Any())
8 {
9 StringBuilder builder = new StringBuilder();
10 realFrameList = realFrameList.Reverse();
11 var lastFrame = realFrameList.Last();
12 builder.AppendFormat("源文件:{0}", lastFrame.GetFileName()).AppendLine();
13 builder.AppendFormat("行号:{0}", lastFrame.GetFileLineNumber()).AppendLine();
14 builder.AppendFormat("方法名:{0}", lastFrame.GetMethod().ToString()).AppendLine();
15 builder.AppendLine("堆栈跟踪:");
16 builder.AppendLine("=================================================================");
17
18 MethodBase method;
19 foreach (var frame in realFrameList)
20 {
21 method = frame.GetMethod();
22 builder.AppendFormat("> {0} 类下的第{1}行 {2} 方法", method.DeclaringType.ToString(), frame.GetFileLineNumber(), method.ToString()).AppendLine();
23 }
24 builder.AppendLine("=================================================================");
25 return builder.ToString();
26 }
27 }
28 return "没有堆栈信息";
29 }

下面这句代码是为了去除.NET FrameWork方法的堆栈跟踪和当前记录日志方法的跟踪,i.GetFileLineNumber() > 0行号大于0表示为获取当前项目方法的堆栈跟踪。

1 var realFrameList = frameList.Where(i => i.GetMethod().DeclaringType != this.GetType() && i.GetFileLineNumber() > 0);

下面我们做个测试:

        [TestMethod]
public void TestTraceSourceLogger()
{
GetMyNumber();
} private int GetMyNumber()
{
ILoggerFactory factory = new TraceSourceLoggerFactory();
LoggerContext.SetCurrent(factory); try
{
var number = int.Parse("我要转成Int32类型");
return number;
}
catch (FormatException)
{
LoggerContext.CreateLog().Error("字符串无法转换为Int32类型");
}
return 0;
}

日志的记录结果如下:

当然也可以将异常的直接扔到StackTrace中,获取详细的堆栈,但是这样无法获取从请求那一刻开始的方法链的跟踪。

还有一个是乎无法解决的问题,就是获取详细的代码行,估计微软也是为了确保程序的安全性吧,要是一不小心显示出关键代码被人拿走了就糟糕了,如果有哪位大牛知道怎么获取的话,麻烦指点指点!!

 
 

StackTrace堆栈跟踪记录详细日志的更多相关文章

  1. 使用StackTrace堆栈跟踪记录详细日志(可获取行号)

    上一篇我们提到使用.NET自带的TraceSource实现简单的日志,具体请看<轻松背后的N+疲惫——系统日志>,这一篇注意想讲的是日志的详细记录,包含请求开始到结束的过程中调用的方法链以 ...

  2. 【C# 异常处理】StackTrace 堆栈跟踪

    作用 在使用.NET编写的代码在debug时很容易进行排查和定位问题,一旦项目上线并出现问题的话那么只能依靠系统日志来进行问题排查和定位,但当项目复杂时,即各种方法间相互调用将导致要获取具体的出错方法 ...

  3. 如何跟踪sharepoint详细日志

    PS C:\Users\setup.moss> Set-SPLogLevel -TraceSeverity verboseexPS C:\Users\setup.moss> New-SPL ...

  4. ASP.NET Core使用Elasticsearch记录NLog日志

    ASP.NET Core使用Elasticsearch记录NLog日志 1.新建一个 ASP.NET Core项目 2.安装Nuge包 运行:Install-Package NLog.Web.AspN ...

  5. Qt5 调试之详细日志文件输出(qInstallMessageHandler)

    注明:以下方法仅适用于 Qt5 及以上版本  函数说明: QtMessageHandler qInstallMessageHandler(QtMessageHandler handler) 此函数在使 ...

  6. Android内存管理(5)*官方教程:Logcat内存日志各字段含义,查看当前内存快照,跟踪记录内存分配,用adb查看内存情况时各行列的含义,捕获内存快照的3种方法,如何让程序暴漏内存泄漏的方法

    Investigating Your RAM Usage In this document Interpreting Log Messages                 内存分析日志中各消息的含 ...

  7. Linux 记录所有用户登录和操作的详细日志

    1.起因 最近Linux服务器上一些文件呗篡改,想追查已经查不到记录了,所以得想个办法记录下所有用户的操作记录. 一般大家通常会采用history来记录,但是history有个缺陷就是默认是1000行 ...

  8. 工作经验:Java 系统记录调用日志,并且记录错误堆栈

    前言:现在有一个系统,主要是为了给其他系统提供数据查询接口的,这个系统上线不会轻易更新,更不会跟随业务系统的更新而更新(这也是有一个数据查询接口系统的原因,解耦).这时,这个系统就需要有一定的方便的线 ...

  9. Django日志记录详细的报错信息

    当服务器500错误的时候,普通日志只会记录一行500的request信息,并不会记录详细的报错定位 [ERROR] 2019-06-12 15:07:03,597 "GET /api/v1/ ...

随机推荐

  1. js中不同的height, top的对比

    每次看到js中的clientHeight(clientTop), offsetHeight(offsetTop),scrollHeight(scrollTop)就头大,根本分不清这几种的区别,然而碰到 ...

  2. SQL Server 2005 MD5函数

    原文:SQL Server 2005 MD5函数 在SQL Server 2005下自带的函数HashBytes() ,此函数是微软在SQL Server 2005中提供的,可以用来计算一个字符串的M ...

  3. 开始学习java

    .net 许久 看网络java猿飞计划,感觉成了少数类,学校为它,有多难不,有着vb,C,javascript和vs基金会,这并不是说一些语法和框架的熟悉做,搞两天,以一个开发环境,myeclipse ...

  4. NSOJ 一个人的旅行(图论)

    虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿 ...

  5. 在LINQ中实现多条件联合主键LEFT JOIN

    我昨天遇到一个LINQ下使用多条件比对产生LEFT JOIN的问题,经过深入研究,终于解决了,也让我学到了新的东西,特地拿来分享. 实例:有一张库存异常变更视图KCYD,仓库ID[Ckid]和物品ID ...

  6. 无废话WCF入门教程二[WCF应用的通信过程]

    一.概述 WCF能够建立一个跨平台的安全.可信赖.事务性的解决方案,是一个WebService,.Net Remoting,Enterprise Service,WSE,MSMQ的并集,有一副很经典的 ...

  7. POJ1258 基础最小生成树

    本文出自:http://blog.csdn.net/svitter 题意:给出一个数字n代表邻接矩阵的大小,随后给出邻接矩阵的值.输出最小生成树的权值. 题解: prime算法的基本解法: 1.选择一 ...

  8. STL之sort函数的用法

    说明:本文仅供学习交流,转载请标明出处,欢迎转载! STL封装了一个排序算法,该算法相应的头文件为#include<algorithm>,我们能够依据须要对一个数组进行排序或者降序. so ...

  9. Cocos2d-x学习笔记(14)(更新函数scheduleUpdate、进度计时器CCProgressTo、滚动视图CCScrollView)

    一.scheduleUpdate 1.scheduleUpdate:此函数是CCNode的函数,每一个CCNode仅仅要调用scheduleUpdate更新函数,那么这个CCNode就会响应当前类的u ...

  10. tomcat加载类的顺序

    /bin:存放启动和关闭tomcat的脚本文件: /conf:存放tomcat的各种配置文件,比如:server.xml /server/lib:存放tomcat服务器所需要的各种jar文件(jar文 ...