2012-09-20 70 views
6

我們繼承了我們想要改進的設計稍差的WCF服務。其中一個問題是它有超過一百種方法(在兩個不同的接口上),其中大多數我們懷疑沒有使用。我們決定在每種方法上進行一些日誌記錄,以跟蹤何時以及如何調用它們。爲了使跟蹤代碼重構友好和錯字證明,我們實現了它,像這樣:然後爲什麼Type.GetInterfaces()有時不會返回有效的列表?

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

不完整的堆棧跟蹤? –

+1

如果你還記錄'callingMethod',你可能會發現它的聲明類型實際上沒有接口。 –

+0

'LogUsage'只能從兩個類中的方法調用,並且這兩個類至少實現一個接口。 – nateirvin

回答

4

StackTrace是臭名昭着的不可靠的,特別是在多線程環境中。或者說,這是非常可靠的,但有時並不是很實際。詢問'最後一次被稱爲'的方法會產生意想不到的結果。嘗試記錄DeclaringType。你可能會驚訝你在那裏找到什麼。請注意,雖然現在這個比例爲0.05%,但隨着應用程序的複雜性可能會增加。

爲了正確實施可重用代碼的跟蹤,你需要依賴於.NET 4.5功能Caller Information,通過使用動態代理(例如Castle Dynamic Proxy),或通過使用AOP框架,如PostSharp。或者,您可以手動編碼跟蹤。響應

+0

「'StackFrame'不是線程安全的」是我考慮的一種可能性;但是,[MSDN文檔](http://msdn.microsoft.com/en-us/library/4ce0ktkk(v = vs.100).aspx)說「StackTrace是用調用者的當前線程創建的」,所以我想我可以依靠它。很高興知道。(由於政治原因,僅供參考)我暫時無法對服務進行任何更改,因此加強日誌記錄不是現在[嘆息]的選項) – nateirvin

3

從埃裏克·利珀特(誰在C#編譯器團隊工程MS)以Getting Type T from a StackFrame

堆棧幀實際上並沒有告訴你誰叫你的方法。 堆棧幀告訴你控制返回的位置。框架 是延續的具體化。事實上,誰叫 方法和控制將返回到哪裏幾乎總是相同的 事情是你的困惑的來源,但我向你保證,他們需要 不一樣。

整個文章是值得一讀的......造成不當重新拋出異常的地方

相關問題