使用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. Hystrix提高系统可用性

    使用Hystrix提高系统可用性 今天稍微复杂点的互联网应用,服务端基本都是分布式的,大量的服务支撑起整个系统,服务之间也难免有大量的依赖关系,依赖都是通过网络连接起来. (图片来源:https:// ...

  2. JQuery插件开发初探——结构熟悉

    工作之余,对Jquery插件做了一点尝试,想着之前总用别人写的插件,自己要是也写一个用岂不是很cool.于是说干就干,动手开始写. 首先是模仿,从一个简单的功能进行入手,了解一下插件开发的流程和结构. ...

  3. 问题(bug)确实不在代码逻辑上面,往往是配置、权限或者业务逻辑之外的地方(转)

    不能说所有的bug都是纸老虎,但往往那种看似很奇葩的bug,导致的原因确实很简单,烦了你一段时间,找到真相又让你忍不住一笑.什么是奇葩的bug呢.我的定义是:代码逻辑都一样,但在A处是好的,到了B处就 ...

  4. hdu 5060 War

    War Time Limit: 8000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  5. js之面向对象----封装篇

    学习了一天的面向对象总结一下,共分为三类 - -! 老规矩 第一部分是概念性知识!!! 面向对象编程,我们可以把他想象成我们在造人.一个对象便是一个人,这个人有胳膊有腿,这便是一个对象的属性或者方法. ...

  6. Android一些解决方案内存问题(一)

    通常我们遇到内存问题时,,解决方案一般有以下的例子: 1.做一些处理上的内存引用,经常使用软引用.加强引用.弱引用: 2.加载在内存中的照片时,它可以处理直接在内存,例如:压缩边界. 3.内存的动态恢 ...

  7. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(1)-框架搭建

    原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(1)-框架搭建 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) 前言:这篇博客开始我们便一步一步的来实现这 ...

  8. Android dumpsys命令的使用

    Android提供的dumpsys工具能够用于查看手机中的应用程序和系统服务信息与状态,手机连接电脑后能够直接命令行运行adb shell dumpsys 查看全部支持的Service可是这样输出的太 ...

  9. 【百度地图API】如何给自定义覆盖物添加事件

    原文:[百度地图API]如何给自定义覆盖物添加事件 摘要: 给marker.lable.circle等Overlay添加事件很简单,直接addEventListener即可.那么,自定义覆盖物的事件应 ...

  10. 又一次拾起C语言的威严

    自从用了C++,他的方便快捷一直用着屡试不爽,可是越用越认为程序不够清晰, 项目使用DSP,不得不把C++重写成C 速度没得说,很快 记录下看到的文章 少走弯路,学好C语言的推荐途径