对于C#日志记录,如何获取调用堆栈深度以最小的开销?

我已经创建了一个log4net的包装(我可能会赞成NLOG的疲态,还没有决定),我缩进记录的消息导致给调用结构的想法。 例如:

2011-04-03 00:20:30,271 [CT] DEBUG - Merlinia.ProcessManager.CentralThread.ProcessAdminCommand - ProcStart - User Info Repository 2011-04-03 00:20:30,271 [CT] DEBUG - Merlinia.ProcessManager.CentralThread.StartOneProcess - User Info Repository 2011-04-03 00:20:30,411 [CT] DEBUG - Merlinia.ProcessManager.CentralThread.SetProcessStatus - Process = User Info Repository, status = ProcStarting 2011-04-03 00:20:30,411 [CT] DEBUG - Merlinia.ProcessManager.CentralThread.SendProcessStatusInfo 2011-04-03 00:20:30,411 [CT] DEBUG - Merlinia.CommonClasses.MhlAdminLayer.SendToAllAdministrators - ProcessTable 2011-04-03 00:20:30,411 [CT] DEBUG - Merlinia.CommonClasses.MReflection.CopyToBinary 2011-04-03 00:20:30,411 [CT] DEBUG - Merlinia.CommonClasses.MReflection.CopyToBinary - False 2011-04-03 00:20:30,411 [CT] DEBUG - Merlinia.CommonClasses.MhlBasicLayer.SendToAllConnections - 228 - True - False 2011-04-03 00:20:30,411 [CT] DEBUG - Merlinia.CommonClasses.MmlNonThreaded.SendObject - 228 2011-04-03 00:20:30,411 [CT] DEBUG - Merlinia.CommonClasses.MllTcpSocket.SendMessage - 228 - True 2011-04-03 00:20:32,174 [10] DEBUG - Merlinia.CommonClasses.MReflection.CreateFromBinary 2011-04-03 00:20:32,174 [10] DEBUG - Merlinia.CommonClasses.MReflection.CopyFromBinary - Bytes = 71 2011-04-03 00:20:32,174 [CT] DEBUG - Merlinia.ProcessManager.CentralThread.MessagingCallback - User Info Repository - ProcessInfoAndRequests 2011-04-03 00:20:32,174 [CT] DEBUG - Merlinia.ProcessManager.CentralThread.ProcessProcessInfoAndRequests - User Info Repository

我做到这一点使用System.Diagnostics.StackTrace和计数StackFrames。

现在,这里的问题:是否有这样做的任何更有效的方法? 我只需要确定的(相对)调用堆栈的深度,即是当前深度加上或减去什么是最后一次我记录的包装被调用。 (请注意,我不实际使用将StackFrame对象 - 我得到的方法名,否则)

什么,我希望的是查询调用堆栈深度或堆栈使用一些简单高效的方式。

--------------解决方案-------------

使用时只需将StackTrace.FrameCount财产,并将其与先前记录的FrameCount 。 仅供参考, FrameCount可能是检索实际帧数最快的方法,因为它只返回内部m_iNumOfFrames现场发回给你。

由于泰奥曼Soygul特别是对奥伦Eini,他的博客泰奥曼提供了一个链接。

下面是一些“概念验证”代码,我认为这是我将使用的解决方案 - 尽管我必须承认我没有做过任何计时测试。

class TestProgram
{
static void Main(string[] args)
{
OneTimeSetup();

int i = GetCallStackDepth(); // i = 10 on my test machine
i = AddOneToNesting(); // Now i = 11
}

private delegate object DGetStackFrameHelper();

private static DGetStackFrameHelper _getStackFrameHelper;

private static FieldInfo _frameCount;

private static void OneTimeSetup()
{
Type stackFrameHelperType =
typeof(object).Assembly.GetType("System.Diagnostics.StackFrameHelper");

MethodInfo getStackFramesInternal =
Type.GetType("System.Diagnostics.StackTrace, mscorlib").GetMethod(
"GetStackFramesInternal", BindingFlags.Static | BindingFlags.NonPublic);

DynamicMethod dynamicMethod = new DynamicMethod(
"GetStackFrameHelper", typeof(object), new Type[0], typeof(StackTrace), true);

ILGenerator generator = dynamicMethod.GetILGenerator();
generator.DeclareLocal(stackFrameHelperType);
generator.Emit(OpCodes.Ldc_I4_0);
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Newobj,
stackFrameHelperType.GetConstructor(new Type[] { typeof(bool), typeof(Thread) }));
generator.Emit(OpCodes.Stloc_0);
generator.Emit(OpCodes.Ldloc_0);
generator.Emit(OpCodes.Ldc_I4_0);
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Call, getStackFramesInternal);
generator.Emit(OpCodes.Ldloc_0);
generator.Emit(OpCodes.Ret);

_getStackFrameHelper =
(DGetStackFrameHelper)dynamicMethod.CreateDelegate(typeof(DGetStackFrameHelper));

_frameCount = stackFrameHelperType.GetField(
"iFrameCount", BindingFlags.NonPublic | BindingFlags.Instance);
}

private static int GetCallStackDepth()
{
return (int)_frameCount.GetValue(_getStackFrameHelper());
}

private static int AddOneToNesting()
{
return GetCallStackDepth();
}
}

分类:C# 时间:2012-06-30 人气:0
本文关键词: 日志记录,调用堆栈
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 0.441 (s). 10 q(s)