C# 面向切面編程(AOP)--監控日志記錄方案


背景:
現在公司整體在做監控平台,要求把各個部分的細節都記錄下來,在前台頁面上有所顯示,所以現在需要做的就是一個監控日志的記錄工作,今天講的就是渲染監控日志的例子。

現狀:
當前的渲染程序沒有為監控日志記錄預留代碼接入口,因此要新增加監控日志勢必要增加新的代碼。但是如果只是單單在已有邏輯中新增日志記錄的代碼似乎不太合理:因為記錄日志的代碼很多都是一樣的,直接插入代碼有很多重復代碼;原有代碼已經上線並且運行良好,新增代碼會破壞原有封裝,甚至增加出錯的可能;再者從設計的角度來說,記錄日志不屬於任何一個功能的,新增日志和每個方法的執行意圖格格不入,因此需要一種新的記錄日志方式。

解決方案:
數據結構:設計一個通用的方法日志記錄類,包含ID,方法名,執行時間長度,日志結果(正常記錄正常信息,異常記錄錯誤信息),日志結果是否為異常標志位等等,還有List<string>包含方法中用到的參變量名稱,List<object>方法中的參變量的值(實現序列化接口或特性),從而實現可以記錄方法上下文信息並幫助排錯。所有方法執行情況日志都用這個類,形成一個統一通用的方法執行狀態信息記錄的類。

記錄方式:
對於所有需要進行日志記錄的方法的采用對該方法所在的類進行動態代理的方式處理。在代理方法中的在原有方法的前后新增日志記錄,動態代理采用裝飾器模式實現通常稱為AOP,AOP方面的內容請參閱: https://msdn.microsoft.com/zh-cn/library/dn574804.aspx 。以上是對已經存在的類的方法進行日志記錄采用動態代理該類,對於方法內部的某個地方進行日志記錄的,采用動態代理Stopwatch來實現。因為方法內部的日志一般都要統計時間長度,動態代理Stopwatch的Start方法和Stop方法,在Start和Stop調用的時后記錄出方法的執行時間和中間參變量的值。

獲取參變量:
對於方法的參數獲取比較容易,動態代理時會把參數傳遞到代理方法中,可以用對象池將該參數的句柄獲取並保存,為防止對象池持有參變量使其不能在退出方法時被垃圾回收器回收,采用弱引用的方式持有所有參變量。對於方法內部的局部變量,采用代理方法中提前實例化保存到對象池方式。對象池采用字典實現,對象池的key用字符串表示,記錄的是方法名稱+變量名+線程上下文哈希值的方式,實現多線程中記錄同一參數不同參數key的后綴(線程上下文哈希值)和不同參數值的記錄,這樣就可以在方法的外部提前獲取局部變量的值並輸出到日志。

對象池實現:
上文提到對象池采用字典存儲,但是對象池何時進行垃圾回收、清理垃圾數據呢?這時我們要自己定義一個添加對象到對象池的方法,在這個方法的第一部分就是清理垃圾數據,這樣每新增一筆數據就刪除舊數據,從而保證對象池的數據有效性。設置局部變量時要在方法執行前的代理方法中就添加,在原有代碼中再添加的時候先從對象池中去取,如果有就用已經用原代碼前添加進去的值,沒有或者已經被垃圾回收了則重新生成新的數據。

源代碼:https://download.csdn.net/download/hirisw/10486250

 

 

出處:https://blog.csdn.net/hirisw/article/details/80734521


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM