2012年5月14日 星期一

MiniProfiler 2.0.1

MiniProfiler 在這個部落格中的很多文章中都有出現過,甚至於也以此為題寫了有四篇的文章:

哪為什麼現在又要再寫一篇有關 MiniProfiler 的文章呢?

這絕對不是為了要佔篇幅(這裡不是報紙也不是雜誌),也不是為了要騙稿費(我找誰要稿費呀),而是因為 MiniProfiler 在 2012-02-22 所發佈更新的 v2.0 有了蠻多的變革,而我卻是遲至今日才開始想寫這些內容,工作忙碌、twMVC 準備工作滿檔、懶?

總之呢 …… 就看下去吧!

 


MiniProfiler 發佈之後,受到了很多人的注意,也有很多人導入專案中使用,然而一個工具的出現總是會有很多的不同意見,例如說,我看到一篇高手高來高去的文章討論:

Ayende @ Rahien - Why I don’t like the MVC Mini Profiler codebase

這一篇的討論就來了兩位 MiniProfiler 開發者 Sam Saffron 與 Marc Gravell 的參與,這些討論不像我們在論壇中所看到的戰文。

其實以上的那篇文章內容與後續的討論也讓我明白,並不一定說使用 MiniProfiler 就需要在程式中去加入一些「侵入式」程式碼,例如:使用 using() …. 把要追蹤的程式區段給包覆起來

var profiler = MiniProfiler.Current; // it's ok if this is null
using (profiler.Step("Set page title"))
{
    ViewBag.Title = "Home Page";
}
using (profiler.Step("Doing complex stuff"))
{
    using (profiler.Step("Step A"))
    { // something more interesting here
        Thread.Sleep(100);
    }
    using (profiler.Step("Step B"))
    { // and here
        Thread.Sleep(250);
    }
}

其實這樣的包覆方式是為了要突顯某一段程式的執行,然後在顯示區塊中顯示,如下我用我專案的程式來做示範,例如以下的程式,我包覆兩個程式區段,一個是 IQueryable 部分,另一個是直接從資料庫取值,

public ActionResult Test2(string city, string columnName, string sort)
{
    using (NorthwindEntities db = new NorthwindEntities())
    {
        var profiler = MiniProfiler.Current;
        using (profiler.Step("Query"))
        {
            PrepareDropDwonLists(city, columnName, sort);
            var query = db.Customers.Select(x => x);
            city = string.IsNullOrWhiteSpace(city) ? "all" : city;
            if (!city.Equals("all"))
            {
                query = query.Where("City == @0", city ?? "London");
            }
            query = query.OrderBy(string.Format
            (
                "{0} {1}",
                string.IsNullOrWhiteSpace(columnName) ? "CompanyName" : columnName,
                string.IsNullOrWhiteSpace(sort) ? "asc" : sort)
            );
            using (profiler.Step("ToList"))
            {
                ViewData.Model = query.ToList();
            }
        }
        return View();
    }
}

在頁面上的顯示視窗就會有這兩個指定突顯的項目,

image

點選 sql 的連結可以看到詳細的內容,

image

 

那如果不使用 using(…) 呢?是否還會在前端頁面的追蹤顯示視窗裡看到這些資訊呢?

public ActionResult Test2(string city, string columnName, string sort)
{
    using (NorthwindEntities db = new NorthwindEntities())
    {
        PrepareDropDwonLists(city, columnName, sort);
        var query = db.Customers.Select(x => x);
        city = string.IsNullOrWhiteSpace(city) ? "all" : city;
        if (!city.Equals("all"))
        {
            query = query.Where("City == @0", city ?? "London");
        }
        query = query
            .OrderBy(string.Format(
                "{0} {1}",
                string.IsNullOrWhiteSpace(columnName) ? "CompanyName" : columnName,
                string.IsNullOrWhiteSpace(sort) ? "asc" : sort));
        ViewData.Model = query.ToList();
        return View();
    }
}

前端的頁面顯示,還是依然會有追蹤到這個 Action 方法中的 sql 執行內容,只不過就沒有去特別的突顯出來,

image

image

所以在不使用 using(…) 把某些程式區段給包覆的情況下,依然可以在前端的追蹤視窗中得到 sql 執行的追蹤內容,只不過如果一個 Action 方法有執行很多的流程步驟的話,就無法清楚地區分出每個流程步驟。

 


MiniProfiler 2.0.1

回到正題,MiniProfiler 在 2012-02-22 發佈了 2.0 的更新版本,這一個版本在命名空間上就做了很大的改變,這是因為要表示 MiniProfiler 不只是應用在 ASP.NET MVC 上,同樣也有支援 ASP.NET WebFroms 與 WCF 的應用。

 

MiniProfiler 官網:http://miniprofiler.com/

image

作者 Sam Saffron 在其部落格中對於 MiniProfiler 2.0 的說明,「Sam Saffron - MiniProfiler 2.0, almost out of the gate」在這篇文章中有詳細說明了 MiniProfiler 2.0 做了哪些的改變,

首先要說明一下命名空間,原本使用 1.9.0 或是 1.9.1 版本的命名空間都會是「MVCMiniProfiler」,

image

image

 

在版本 v2.0.0 以後都將給使用新的命名空間「StackExchange.Profiling

image

在程式中建立一個 MiniProfiler instance 還是一樣的方式,

image

 


實作

光說不練的話是不行的,雖然之前的文章已經有詳盡的安裝說明了,既然是要寫,就還是把安裝步驟大致交代好了…

 

Step.1

先準備好一個 ASP.NET MVC 3 的網站專案,並且在這個 MVC 專案中也建立好一個 ADO.NET Entity Framework 的 Model

image

 

Step.2

使用 Nuget 逐一安裝以下的套件

  • Entity Framework 4.3.1
  • jQuery 1.7.2
  • MiniProfiler 2.0.1
  • MiniProfiler.MVC3 2.0.1
  • MiniProfiler.EF 2.0.2

SNAGHTML612642e

安裝完成後,MiniProfiler 會在我們的專案中增加兩個檔案,

image

 

Step.3

修改 View 的 主版頁面「_Layout.cshtml」內容,其實可以照著「_MINIPROFILER_UPDATED_Layout.cshtml」內容來複製貼上,但是 MiniProfiler v.2.0.1 有增加了很多的功能與屬性,所以如果對於 MiniProfiler 比較陌生的朋友還是建議照著以下的方式進行,在最上方的地方加入「StackExchange.Profiling」的引用,然後就是網頁最下面的地方,也就是在 </body> 的上方加上「@MiniProfiler.RenderIncludes()

image

之前版本中的「@MiniProfiler.RenderIncludes()」是加在 <body> 的下方,但因為這個方法主要是網頁在 Render 時加入一段 JS 程式,因為顧及到網頁效能的影響,網頁中的 JS 程式以及引用 Javascript 程式檔案都盡量放置在網頁的最下方,如此才不會影響到網頁中各個元素的 Render,好了,以上的步驟都完成之後就可以執行網站專案,來測試看看 MiniProfiler 是否有正確的安裝到專案中,

image

點開右上角的白色區塊,就會顯示網頁執行的追蹤內容,

image

再點擊追蹤視窗的「show trivial」還可以顯示更多的執行資訊,

image

如果是點擊「share」就可以顯示當前追蹤資訊的單一資料頁面,

image

image

每一次網頁的執行都有獨立的追蹤資料,所以就可以保留每一次執行的追蹤資料內容,用於程式執行的比對與偵測上有很大的幫助。如果之前有使用過 MiniProifiler 之前版本而還沒有使用過 v2.0.0 之後新版本的人一定會覺得這次需要手動修改程式的地方便少了,而且開啟 Global.asax 之後可以發現,到目前為止的步驟裡,還不必去修改到 Global.asax。

 

Step.4

現在我們在 HomeController 裡加上一個新的 Action 方法,然後在這個方法增加透過 EF 取得資料的程式,

image

接著為了要讓 MiniProfiler 可以偵測到 EF 執行的 SQL Command,所以還必須調整「~/App_Start/MiniProfiler.cs」的程式內容,將第 9 ~ 11 行以及第 42 行給解除註解,

image

修改後就可以執行看結果囉(記得要加入 Index2 的 View 呀!)

執行的網頁顯示結果,

image

看看所偵測的 EF 執行 SQL Command 內容,

image

 


 

Profiler Popup 調整

基本上,前面四個步驟已經完成的 MiniProfiler 的安裝與使用,那還需要介紹什麼呢?

這裡要介紹調整追蹤資料顯示視窗的方法,調整的地方有兩個地方,一個是在 View 而另一個要在 Global.asax 之中,先來看看在「_Layout.cshtml」的調整,可以在 MiniProfiler.RenderIncludes() 方法中加入參數,

@MiniProfiler.RenderIncludes(position: RenderPosition.Right, showTrivial: false, showTimeWithChildren: false)

看不清楚圖片的,可以另開圖片到新視窗中,會比較清楚,

image

藉由五個參數的加入,可以調整追蹤視窗的顯示,比較常用到的就三個:position, showTrivial, showTimeWithChildren,看看調整前的追蹤資料顯示視窗,

image

調整之後,

image

可以看到追蹤資料顯示視窗由網頁的左上方換到網頁的右上方顯示,原本預設不會顯示的 Time With Children 與 Trivial 資料都變成預設為顯示。

 

第二種調整的方式就是要在 Global.asax 裡去增加調整的程式,在 Global.asax 中的 Application_Start 方法加入程式,以程式的方式對頁面的追蹤資料顯示視窗做調整,而原本在「_Layout.cshtml」的 MiniProfiler.RederIncludes() 就恢復原狀,

image

修改後,再一次執行網頁, Time With Children 與 Trilval 資料變回了之前預設的不顯示

image

MiniProfiler.Settings 還有很多屬性可以做設定,有些比較基本而有些就比較進階,這邊就不多做討論,有興趣的朋友可以自己試試,以下是比較常用的幾個設定屬性,各位可以調整幾個屬性,看看頁面上的 Profile Popup 有什麼不同與改變,

private void InitProfilerSettings()
{
    MiniProfiler.Settings.PopupRenderPosition = RenderPosition.Right;   //defaults to left
    MiniProfiler.Settings.PopupMaxTracesToShow = 20;                    //defaults to 15
    MiniProfiler.Settings.RouteBasePath = "~/profiler";                 //e.g. /profiler/mini-profiler-includes.js
    MiniProfiler.Settings.StackMaxLength = 256;                         // default is 120 characters
    MiniProfiler.Settings.PopupShowTrivial = true;
    MiniProfiler.Settings.PopupShowTimeWithChildren = true;
}

 


先寫到這裡為止,其實還有很多新增的功能可以介紹給大家,但也不需要一次就全部塞給大家,一次全給,也未必能夠消化,如果大家不想等我下一篇的進階介紹或是想要自己研究,建議各位可以到前面有介紹過的,MiniProfiler 作者所寫的文章「Sam Saffron - MiniProfiler 2.0, almost out of the gate」,而如果想要知道這個 MiniProfiler 的結構與原始碼內容,則是可以到官網上下載或是 github 下載,

官網 - http://miniprofiler.com/

github - https://github.com/SamSaffron/MiniProfiler

如果對於 MiniProfiler 使用上有任何的問題,則是可以到 MiniProfiler 的討論區中發問,

http://community.miniprofiler.com/

或者也可以到 stackoverflow 中查看有關「mini-profiler」Tag 的提問與解答內容

http://stackoverflow.com/questions/tagged/mini-profiler

 

以上

2 則留言:

  1. 您好
    今天按照文章實作時發現到
    "然後就是網頁最下面的地方,也就是在 /body 的上方加上「@MiniProfiler.RederIncludes()」"
    打錯了
    @MiniProfiler.RenderIncludes()
    才對

    感謝您寫這文章教學

    回覆刪除

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。