企业级日志组件应该包含哪些信息?如下:
1. Severity:严重程度
2. AppDomain:应用程序域
3. ExceptionName:异常类型名
4. Message:异常消息
5. Source:异常来源
6. StackTrace:异常堆栈信息
7. Assembly:异常来自的程序集
8. Method:异常来自的方法
9. Machine:异常来自的机器
10. UserName:异常来自的用户名
11. ThreadName:异常来自的线程名
12. CreationDatetime:异常发生的时间
我们定义ExceptionEnvironmentInfo类:
public class ExceptionEnvironmentInfo
{
public string MachineName;
public DateTime TimeStamp;
public string AppDomainName;
public string ThreadIdentity;
public string WindowsIdentity;
public string Method;
public string AssemblyName;
public string AssemblyFullName;
public StackFrame[] StackTrace;
public string GetStackTrace()
{
if (this.StackTrace == null || this.StackTrace.Length == 0)
{
return string.Empty;
}
try
{
var sb = new StringBuilder();
bool hasFileInfo = !string.IsNullOrEmpty(this.StackTrace[0].GetFileName());
foreach (var frame in StackTrace)
{
var method = frame.GetMethod();
sb.AppendFormat("at {0}.{1}", method.DeclaringType.FullName, method.Name);
if (hasFileInfo)
{
sb.AppendFormat(" in {0}:line {1}", frame.GetFileName(), frame.GetFileLineNumber());
}
sb.AppendLine();
}
return sb.ToString();
}
catch (Exception ex)
{
return "Error getting stack trace: " + ex.Message;
}
}
}
定义一个ExceptionInfo类:
public class ExceptionInfo
{
public readonly Exception Exception;
public readonly ExceptionEnvironmentInfo EnvironmentInfo;
public ExceptionInfo(Exception ex, ExceptionEnvironmentInfo envInfo)
{
this.Exception = ex;
this.EnvironmentInfo = envInfo;
}
}
通过这两个类可以保存所有我们关心的信息。
我们现在对上面列出来的信息,如何获取,进行一一讨论。
1. Severity:严重程度
这个信息是用户在记录异常的时候,由用户决定的。
2. AppDomain:应用程序域
AppDomain.CurrentDomain.FriendlyName;
3. ExceptionName:异常类型名
ex.GetType().Name;
4. Message:异常消息
ex.Message;
5. Source:异常来源
ex.Source;
6. StackTrace:异常堆栈信息
ex.StackTrace;
7. Assembly:异常来自的程序集
8. Method:异常来自的方法
这两个信息需要使用StackTrace来计算出来,具体看后面的ExceptionManager类的实现。
9. Machine:异常来自的机器
Environment.MachineName;
10. UserName:异常来自的用户名
System.Security.Principal.WindowsIdentity.GetCurrent().Name;
11. ThreadName:异常来自的线程名
System.Threading.Thread.CurrentPrincipal.Identity.Name;
12. CreationDatetime:异常发生的时间
DateTime.Now;
ExceptionManager类的实现:
public class ExceptionManager
{
private Type _callerStackBoundaryDeclaringType = typeof(ExceptionManager);
public void Publish(Exception ex)
{
ExceptionEnvironmentInfo envInfo = GetEnvironmentInfo();
var exInfo = new ExceptionInfo(ex, envInfo);
//TODO: save the exInfo in database.
//...
}
private ExceptionEnvironmentInfo GetEnvironmentInfo()
{
ExceptionEnvironmentInfo envInfo = new ExceptionEnvironmentInfo();
this.GetCallerInfo(envInfo);
// Add environment information to the information collection.
envInfo.MachineName = Environment.MachineName;
envInfo.TimeStamp = DateTime.Now;
envInfo.AppDomainName = AppDomain.CurrentDomain.FriendlyName;
envInfo.ThreadIdentity = System.Threading.Thread.CurrentPrincipal.Identity.Name;
envInfo.WindowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
return envInfo;
}
private void GetCallerInfo(ExceptionEnvironmentInfo envInfo)
{
bool fNeedFileInfo = false;
#if DEBUG
fNeedFileInfo = true;
#endif
var st = new StackTrace(fNeedFileInfo);
try
{
var index = 0;
// 首先根据堆栈信息定位到ExceptionManager的调用帧信息
while (index < st.FrameCount)
{
var frame = st.GetFrame(index);
if (frame != null && frame.GetMethod().DeclaringType == _callerStackBoundaryDeclaringType)
{
index++;
break;
}
index++;
}
// 然后过滤掉所有来自ExceptionManager的调用帧信息,因为ExceptionManager是底层通用组件,需要过滤掉
while (index < st.FrameCount)
{
var frame = st.GetFrame(index);
if (frame != null && frame.GetMethod().DeclaringType != _callerStackBoundaryDeclaringType)
{
break;
}
index++;
}
// 这个是异常出现的真实位置,记录来它的所有的帧
if (index < st.FrameCount)
{
var frames = new StackFrame[st.FrameCount - index];
for (int i = 0; i + index < st.FrameCount; i++)
{
frames[i] = st.GetFrame(i + index);
}
var method = frames[0].GetMethod();
var declaringType = method.DeclaringType;
var callingAssembly = declaringType.Assembly;
var callingAssemblyName = declaringType.Assembly.GetName();
envInfo.StackTrace = frames;
envInfo.AssemblyName = callingAssemblyName.Name;
envInfo.AssemblyFullName = callingAssemblyName.FullName;
envInfo.Method = string.Format("{0}.{1} ({2})", declaringType.FullName, method.Name, envInfo.AssemblyName);
}
}
catch (Exception e)
{
envInfo.Method = "(unobtainable)(error: " + e.Message + ")";
}
}
}
然后在自己的业务逻辑代码里面就可以获取到所有的异常信息了,并且会正确返回程序集和方法信息:
public void DoBiz()
{
try
{
throw new Exception("Error happen!");
}
catch (Exception ex)
{
ExceptionManager manager = new ExceptionManager();
manager.Publish(ex);
}
}
-纸上得来终觉浅,绝知此事要躬行-
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有