使用Filter跟蹤Asp.net MVC頁面加載時間

最近,客戶一直反饋系統使用慢,有時候可以指出具體是哪一個頁面,有時候又只是籠統地反饋慢。這種問題就像是幽靈同樣,很是很差處理。由於致使這種問題的因素很是之多,並且在開發工程中,很難模擬出實際運行是的環境。理論上,對於全部的頁面作壓力測試是個解決方案,可是這種方式的成本過高,又沒有辦法很快地定位和解決客戶的問題。html

最後,考慮經過建立Filter來在訪問Action以前記錄一個時間,在頁面Render完成以後,再記錄一下時間。經過比較這2個時間的差值來跟蹤每一個頁面的加載性能。若是對於MVC中的Filter還不太熟悉,能夠看這裏Asp.net MVC使用Filter解除Session, Cookie等依賴,文章有對於Filter的介紹和使用。ide

言歸正傳,直接上代碼。經過繼承ActionFilterAttribute, 分別重寫OnActionExecutingOnResultExecuted方法。性能

public class TrackPageLoadPerformanceAttribute : ActionFilterAttribute
   {

      //這裏使用log4net來打印出結果
       private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

      //建立字典來記錄開始時間,key是訪問的線程Id.
       private readonly Dictionary<int, DateTime> _start = new Dictionary<int, DateTime>();

      //建立字典來記錄當前訪問的頁面Url.
       private readonly Dictionary<int, string > _url = new Dictionary<int, string>();

       public override void OnActionExecuting(ActionExecutingContext filterContext)
       {
           //過濾掉ChildAction, 由於ChildAction實際上不是一個單獨的頁面
           if(filterContext.IsChildAction) return;

           var currentThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;

           try
           {
               _start.Add(currentThreadId, DateTime.Now);
               _url.Add(currentThreadId, filterContext.HttpContext.Request.Url == null
                   ? string.Empty
                   : filterContext.HttpContext.Request.Url.AbsoluteUri);
           }
           catch (Exception ex)
           {
               Log.Error(ex.ToString());
           }
       }

       public override void OnResultExecuted(ResultExecutedContext filterContext)
       {
           var currentThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
           if (!_start.ContainsKey(currentThreadId)) return;

           try
           {

                //計算出當前頁面訪問耗時
               var costSeconds = (DateTime.Now - _start[currentThreadId]).TotalSeconds;
               if (costSeconds > 2)//若是耗時超過2秒,就是用log4net打印出,具體是哪一個頁面訪問超過了2秒,具體使用了多長時間。
               {
                   Log.Info(string.Format("Access the action more than 2 seconds. cost seconds {1}.  URL: {0}", _url[currentThreadId], costSeconds));
               }
           }
           catch (Exception ex)
           {
               Log.Error(ex.ToString());
           }
           finally
           {
               _start.Remove(currentThreadId);
               _url.Remove(currentThreadId);
           }
       }
   }

最後,將該Filter註冊成Global Filter,這樣,就能監控系統中全部頁面的加載時間了.測試

image

若是你也遇到和我相似的性能問題,不妨試試,加上這個Filter, online系統中哪一個頁面慢,就可以一目瞭然了。
關於Asp.net MVC性能監控,還有這篇文章可能能幫到你。使用MiniProfiler給Asp.net MVC和Entity Framework號脈(附源碼)url

相關文章
相關標籤/搜索