使用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. Android项目打包成APK文件

    第一步:右键单击该项目选择Export项目 显演示样例如以下界面:选择Exprot Android Application 第二步:输入项目名称,默认的情况下是原始的项目名称 下一步: 点击 Crea ...

  2. JavaEE(3) - RMI服务器和客户端

    1. 开发RMI服务器 Net Beans创建java project: (qs) (Server.java) package server; import java.rmi.*; //远程接口必须集 ...

  3. docker study

    Author:Hyphen 同步公布在个人博客中:http://yanheven.github.io/docker-study/ 參考章宇兄的开源项目学习ABC的方法来对docker进行简单的学习与分 ...

  4. hdu 游乐场

    Problem Description   小时候,因为家里经济困难,小明从未去过游乐场,所以直到现在,他还心存遗憾.  最近,杭州刚建了一座游乐场,为了弥补儿时的遗憾,小明带了一笔钱迫不及待地要去体 ...

  5. 豆瓣api之OAuth认证

    豆瓣api通过OAuth允许第三方应用访问用户数据,所以OAuth认证就是我们整个project的基础了. OAuth认证听起来挺神秘,其实挺简单的. 现在的大型网站的开放平台的认证几乎都是采用OAu ...

  6. Cannot find ActionMappings or ActionFormBeans collection

    出现此问题.首先检查web.xml,的主要结构被认为是在下面的图: 再检查struts-config.xml.确认是否有<form-beans>和<action-mappings&g ...

  7. MyReport报表引擎2.7.6.7新功能

    新增二维码控件PDF417 设计器新增数据选项卡,可以拖放字段进行绑定   相关链接 MyReport演示.产品站点 相关文章 MyReport专栏

  8. python解析命令行

    可以解析这样的命令 ./cron_ctrl jobname1 --stop ;./cron_ctrl jobname1 --start;./cron_ctrl jobname1 --list #!/u ...

  9. 程序员面试必备经典CTCI,谷歌面试官经典作品!

    1.1 判断一个字符串中的字符是否唯一 1.2 字符串翻转 1.3 去除字符串中重复字符 1.8 利用已知函数判断字符串是否为另一字符串的子串 2.1 从链表中移除重复结点 2.2 实现一个算法从一个 ...

  10. XAMPP on Mac 组态 Virual Host

    首先,在hosts文件中添加virtual host域名.方向127.0.0.1 我一般使用的命名约定dev-domainname.com sudo nano /private/etc/hosts # ...