使用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. Telephone Lines USACO 月赛

    以前做过这套题目 这个题又重新写了:http://www.cnblogs.com/jh818012/archive/2013/05/05/3182681.html 还是以前的思路 一直错在一个地方:决 ...

  2. Cocos2d-x 文本渲染

     文本渲染: CCLabelAtlas.CCLabelBMFont.CCLabelTTF类都是继承 CCLabelProtocol类,即能够使用系统字,也能够自己定义渲染字体. CCLabelAtla ...

  3. Theano学习笔记(三)——图结构

    图结构(Graph Structures)这是理解Theano该基金会的内部运作. Theano编程的核心是用符号占位符把数学关系表示出来. 图结构的组成部分 如图实现了这段代码: importthe ...

  4. ios正在使用NSDateComponents、NSDate、NSCalendar它的结论是在当前时间是在一段时间在一天。

    一般应用程序设置这一组的存在,比如夜间模式,如果你.从8:00-23:00.在这个当前的时间是如何推断出期间.主要的困难在于如何使用NSDate生成8:00时间和23:00时间.然后用当前时间,也许有 ...

  5. 如何用Excel直接查询Oracle中的数据(转)

    将Oracle中查询的数据保存为Excel文件,通常使用的是PL/SQL Developer. 其实,Excel可直接写SQL语句查询Oracle中数据,在这里,用到ODBC驱动.详细步骤如下: 一. ...

  6. URAL 1404. Easy to Hack! (模拟)

    space=1&num=1404">1404. Easy to Hack! Time limit: 1.0 second Memory limit: 64 MB When Vi ...

  7. 小程序大智慧,sqlserver 注释提取工具

    原文:小程序大智慧,sqlserver 注释提取工具 开篇背景 我习惯在写表的创建脚本时将注释直接写在脚本里,比如 /*账套*/ CREATE TABLE [dbo].[AccountingBook] ...

  8. javascript获取浏览器窗口大小办法

    四个属性: 1:outerWidth  2:outerHeight  3:innerWidth  4:innerHeight 经最新版本的浏览器(Chrom IE Firefox Opera)测试,初 ...

  9. ProgressDialog(四)——更改系统自带ProgressDialog文字大小

    MainActivity如下面: package com.example.ttt; import android.app.Activity; import android.app.ProgressDi ...

  10. 【百度地图API】如何判断点击的是地图还是覆盖物?

    原文:[百度地图API]如何判断点击的是地图还是覆盖物? 摘要:很多API爱好者问我,为什么我点击的是marker,而map也会响应该事件呢?怎样才能判断,我点击的是标注,还是地图呢?下面一起来看看. ...