使用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. apk当安装程序将文件复制到手机自带的指定文件夹

    项目已获得,今天.apk文件以获得另一个非调试手机,发现一个问题. 由于涂料.所以绘图数据的点存储在一个.txt文字档.把它用usb传到指定目录下的,可是明显不科学,由于用户下载了你的.apk文件,你 ...

  2. 第一次测试HTML和CSS

    1.HTML(Hyper Text Markup Languange)超文本标记语言.HTML文件扩展名通常是:htm和html. <html> <head> <titl ...

  3. 【SICP练习】150 练习4.6

    练习4-6 原版的 Exercise 4.6. Let expressions are derived expressions, because (let (( ) - ( )) ) is equiv ...

  4. java_Eclipse自动生成作者、日期注释等功能设置_导入 xml方式

    常规方式 随便百度个 类比 http://blog.sina.com.cn/s/blog_4080505a0101guoh.html 这里主要介绍配好后,导出,xml,迁移环境时 导入 comment ...

  5. 今天才知道css hack是什么

    先来个冷笑话:一晚下班回家,一民警迎面巡逻而来.突然对我大喊:站住! 民警:int类型占几个字节? 我:4个. 民警:你可以走了. 我感到很诧异. 我:为什么问这样的问题? 民警:深夜还在街上走,寒酸 ...

  6. Python的html和xml解析库Beautiful Soup

    网站:http://www.crummy.com/software/BeautifulSoup/ 版权声明:本文博主原创文章,博客,未经同意不得转载.

  7. 关于Cassandra与Thrift在int/text/varint上的暧昧

    近期简单写了一个基于Cassandra/C++的日志缓存,虽然是Nosql,但是在实际应用中,还是期望能有部分的临时CQL统计 或+-*/可以支持 所以在针对部分字段入库时,选择了作为整形录入,于是麻 ...

  8. 怎样选择PHP的版本

    原文:怎样选择PHP的版本 IIS 如果想使用IIS配置PHP的话,那么需要选择Non-Thread Safe(NTS)版本的PHP Apache 如果你是用的Apache的版本来自Apache Lo ...

  9. Access denied for user: &#39;root@localhost&#39; (Using password: YES)

    centos 设备mysql成功后 首次使用root登录发生:Access denied for user: 'root@localhost' (Using password: YES) 因为mysq ...

  10. LCD开发之汉字显示

    一.LCD显示原理 利用液晶制成的显示器称为LCD,根据驱动方式可分为静态驱动.简单矩阵驱动以及主动矩阵驱动3种.当中,简单矩阵型又可再细分扭转向列型(TN)和超扭转式向列型(STN)两种,而主动矩阵 ...