我们继承了一个设计不合理的WCF服务,我们希望改进它。它的一个问题是它有超过一百种方法(在两个不同的接口上),其中大多数我们怀疑没有使用。我们决定对每种方法进行一些记录,以跟踪它们何时以及如何被调用。为了使跟踪代码具有重构友好性和防错性,我们实现了它:
public void LogUsage()
{
try
{
MethodBase callingMethod = new StackTrace().GetFrame(1).GetMethod();
string interfaceName = callingMethod.DeclaringType.GetInterfaces()[0].Name;
_loggingDao.LogUsage(interfaceName, callingMethod.Name, GetClientAddress(), GetCallingUrl());
}
catch (Exception exception)
{
_legacyLogger.Error("Error in usage tracking", exception);
}
}
然后在我们想要跟踪的每个方法的开头调用 LogUsage()
。
该服务的流量非常高,每天有500,000多个电话。 99.95%的时间,这段代码执行得很漂亮。但是另外0.05%的时间,GetInterfaces()
返回一个空的(但不是null
)数组。
为什么GetInterfaces()
偶尔会返回不一致的结果?
这看起来似乎微不足道 - 0.05%的错误率是我们通常只能梦想的。但重点是识别所有服务接触点,如果此错误总是来自一个(或几个)方法调用,那么我们的跟踪是不完整的。我试图通过调用服务上的每个方法在我的开发环境中重现此错误,但无济于事。
答案 0 :(得分:4)
StackTrace
不可靠,尤其是在多线程环境中。或者说,它非常可靠,但有时不太实用。询问“最后一个被调用的方法”会产生意想不到的结果。尝试记录DeclaringType。您可能会对在那里找到的东西感到惊讶。请注意,虽然现在这是一个0.05%的失败率,但随着应用程序的复杂性,它很容易增加。
为了正确实现可重用的跟踪代码,您需要依赖.NET 4.5功能Caller Information,使用动态代理(例如Castle Dynamic Proxy)或使用AOP框架例如PostSharp。或者,您可以手动编写跟踪代码。
答案 1 :(得分:3)
来自Erik Lippert(负责MS的C#编译团队)回应Getting Type T from a StackFrame:
堆栈框架实际上并没有告诉你谁调用了你的方法。该 堆栈框架告诉您控件将返回的位置。堆栈 框架是延续的具体化。谁叫谁的事实 方法和控制将返回的位置几乎总是相同的 事情是你困惑的根源,但我向你保证他们需要 不一样。
整个帖子值得一读......