{"id":101,"date":"2012-01-17T11:58:52","date_gmt":"2012-01-17T13:58:52","guid":{"rendered":"http:\/\/blog.iordanov.info\/?p=101"},"modified":"2012-01-17T16:39:38","modified_gmt":"2012-01-17T18:39:38","slug":"monitoring-page-generation-and-page-load-time-in-mvc-3-net","status":"publish","type":"post","link":"https:\/\/blog.iordanov.info\/?p=101","title":{"rendered":"Monitoring Page Generation and Page Load Time in MVC 3 .Net."},"content":{"rendered":"<p>It seems that many post concern .Net development hints do not care about the reader. That\u2019s I decided to write this blog collecting information from difference places and putting together. There are some additional helpful things from me\u2026<\/p>\n<p><a href=\"https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/mvc-4-i.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-medium wp-image-107\" title=\" Page Load and Page Generation time\" src=\"https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/mvc-4-i-300x272.png\" alt=\"\" width=\"300\" height=\"272\" srcset=\"https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/mvc-4-i-300x272.png 300w, https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/mvc-4-i.png 444w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>This post is intended to show a very simple and comfortable way to monitor web page generation and load time in your web application. It uses a java script and a IHttpModule implementation in MVC 3 .Net environment.<\/p>\n<p>The measurements are divided in 2\u00a0: Page Load and Page Generation time.<\/p>\n<h3>Page Load Time<\/h3>\n<p>Let\u2019s make a short definition of Page Load Time. This is a time showing how long it takes for a page to load. A timer starts when the page begins to parse and ends when it has completed loading all of the content. The measurement of this time is a suitable task for java script implementation. Some examples can be found in Loading Time<sup id=\"cite_ref-Joff2012_0-0\">[1]<\/sup>\u00a0and Indicator JavaScript Web Page Load Time<sup id=\"cite_ref-Hash2011_1-0\">[2]<\/sup>\u00a0web publications. Both are based on using\u00a0<a title=\"http:\/\/www.w3schools.com\/js\/js_timing.asp\" href=\"http:\/\/www.w3schools.com\/js\/js_timing.asp\" rel=\"nofollow\">JavaScript Timing Events<\/a>.<\/p>\n<h3>Page Generation Time<\/h3>\n<p>&#8220;Page Generation Time&#8221; measure how long it took for a page to be generated by the server. Some short and working examples how to do this in .Net MVC environment can be found in stackoverflow<sup id=\"cite_ref-JOBG2009_2-0\">[3]<\/sup>\u00a0and Pro ASP.NET MVC Framework by Steven Sanderson &#8211; Chapter 15 &#8211; Performance, Monitoring Page Generation Times<sup id=\"cite_ref-Sand2009_3-0\">[4]<\/sup>.<\/p>\n<h3>My Implementation<\/h3>\n<p><a href=\"https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/Clipboard011.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-120\" title=\"Clipboard01\" src=\"https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/Clipboard011.jpg\" alt=\"\" width=\"460\" height=\"57\" srcset=\"https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/Clipboard011.jpg 460w, https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/Clipboard011-300x37.jpg 300w\" sizes=\"auto, (max-width: 460px) 100vw, 460px\" \/><\/a>In the following example I made some additions to the above pointed examples to allow page generation and page load times measurement in case of AJAX request.<\/p>\n<h4>1 Java Script<\/h4>\n<p>Put in a java script file the folloing variables and functions:<\/p>\n<pre>  \/***************************** TIMER Page Load *******************************\/\r\n  var loopTime;\r\n  var startTime = new Date();\r\n  var pageGenerationTime = \"0.0\";\r\n\r\n  function pageloadTimerCount() {\r\n   loopTime = setTimeout(\"pageloadTimerCount()\", 100);\r\n  }\r\n\r\n  function pageloadDoTimer() {\r\n       pageloadTimerCount();\r\n  }\r\n\r\n  function pageloadStopTimer() {\r\n     var timeMs = Math.floor((new Date() - startTime)); \r\n\r\n     $('#loadtime').html(\"\" + timeMs );\r\n     $('#generatetime').html(pageGenerationTime);\r\n     $('#pagetime').show();\r\n\r\n     clearTimeout(loopTime);\r\n  }<\/pre>\n<p><a name=\"_Layout.cshtml\"><\/a><\/p>\n<h4>2 _Layout.cshtml<\/h4>\n<p><a name=\"Include_Reference_of_the_above_JS_file\"><\/a><\/p>\n<h5>2.1 Include Reference of the above JS file<\/h5>\n<p><a name=\"In_the_beginning_oh_HEAD_tag_include_startTime_initialization:\"><\/a><\/p>\n<h5>2.2 In the beginning oh HEAD tag include\u00a0<em>startTime<\/em>\u00a0initialization:<\/h5>\n<pre>  &lt;head&gt;\r\n    &lt;script type=\"text\/javascript\"&gt;\r\n        var startTime = new Date();\r\n    &lt;\/script&gt;\r\n    .....\r\n  &lt;\/head&gt;<\/pre>\n<p><a name=\"In_Page_body_tag_include_a_similar_DIV_like_this_one:\"><\/a><\/p>\n<h5>2.3 In Page\u00a0<strong>body<\/strong>\u00a0tag include a similar\u00a0<strong>DIV<\/strong>\u00a0like this one:<\/h5>\n<pre>     &lt;div id=\"pagetime\" style=\"display:none;\"&gt;\r\n       Page Generation: &lt;span id=\"generatetime\"&gt;0.0&lt;\/span&gt; Page Load: &lt;span id=\"loadtime\"&gt;0.0&lt;\/span&gt; ms.\r\n     &lt;\/div&gt;<\/pre>\n<p><a name=\"In_the_end_of_page_include:\"><\/a><\/p>\n<h5>2.4 In the end of page include:<\/h5>\n<pre>   &lt;script type=\"text\/javascript\"&gt;\r\n   $(document).ready(function () {pageloadDoTimer();});\r\n    &lt;\/script&gt;<\/pre>\n<p><a name=\"Performance_Monitor_Module\"><\/a><\/p>\n<h4>3 Performance Monitor Module<\/h4>\n<p>Create and Register a Custom HTTP Module &#8211;\u00a0<em>PerformanceMonitorModule<\/em>. The similar modul is described in Pro ASP.NET MVC Framework by Steven Sanderson &#8211; Chapter 15 &#8211; Performance, Monitoring Page Generation Times<sup id=\"cite_ref-Sand2009_3-1\">[4]<\/sup>\u00a0and some help reference can be found in in\u00a0<a title=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms227673.aspx\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms227673.aspx\" rel=\"nofollow\">MSDN Library<\/a>.<\/p>\n<pre> using System;\r\n using System.Collections.Generic;\r\n using System.Linq;\r\n using System.Web;\r\n using System.Diagnostics;\r\n\r\n namespace Website.Module\r\n {\r\n   public class PerformanceMonitorModule\u00a0: IHttpModule\r\n   {\r\n       public void Dispose() { \/* Nothing to do *\/ }\r\n       public void Init(HttpApplication context)\r\n       {\r\n           context.PreRequestHandlerExecute += delegate(object sender, EventArgs e)\r\n           {\r\n               HttpContext requestContext = ((HttpApplication)sender).Context;\r\n               Stopwatch timer = new Stopwatch();\r\n               requestContext.Items[\"Timer\"] = timer;\r\n               timer.Start();\r\n           };\r\n           context.PostRequestHandlerExecute += delegate(object sender, EventArgs e)\r\n           {\r\n               HttpContext requestContext = ((HttpApplication)sender).Context;\r\n\r\n               Stopwatch timer = (Stopwatch)requestContext.Items[\"Timer\"];\r\n               timer.Stop();\r\n               \/\/ Don't interfere with non-HTML responses \r\n\r\n                   if (requestContext.Response.ContentType == \"text\/html\" ||\r\n                       requestContext.Response.ContentType == \"application\/json\")\r\n                   {\r\n\r\n                           Uri requestUrl = requestContext.Request.Url;\r\n                           double ms = (double)timer.ElapsedMilliseconds;\r\n                           string result = string.Format(\"{0:F0} ms.\", ms);\r\n\r\n                           requestContext.Response.Write(\r\n                                   \"&lt;script type=\\\"text\/javascript\\\"&gt;\r\n                                       var pageGenerationTime = '\" + result + \"';\r\n                                       pageloadStopTimer();\r\n                                    &lt;\/script&gt;\");\r\n\r\n                   }\r\n           };\r\n       }\r\n   }\r\n }<\/pre>\n<p>PerformanceMonitorModule Registration in Web.Config:<\/p>\n<pre> &lt;configuration&gt;\r\n ...\r\n   &lt;system.web&gt;\r\n   ...\r\n     &lt;httpModules&gt;\r\n       &lt;add name=\"PerfModule\" type=\"Website.Module.PerformanceMonitorModule, Reports.Website\"\/&gt;\r\n     &lt;\/httpModules&gt;\r\n    ...\r\n   &lt;\/system.web&gt;\r\n ...\r\n &lt;\/configuration&gt;<\/pre>\n<p><a name=\"Partial_Views\"><\/a><\/p>\n<h4>4 Partial Views<\/h4>\n<p>In partial views used for AJAX request put the following in the beginning of the page:<\/p>\n<pre>  &lt;script type=\"text\/javascript\"&gt;\r\n      var startTime = new Date();\r\n  &lt;\/script&gt;<\/pre>\n<p><a name=\"CSS\"><\/a><\/p>\n<h4>5 CSS<\/h4>\n<p>In my implementation I am using the following css that shows time values under main menu on the page.<\/p>\n<pre>  #pagetime\r\n  {\r\n   position: absolute;\r\n   width: 325px;\r\n   left: 55%;\r\n   margin: -22px auto 2px auto;\r\n   z-index:6;\r\n   padding: 2px;\r\n   color: #F47511;\r\n   text-align:center;\r\n   font-size:x-small;\r\n   font-style:italic;\r\n }<\/pre>\n<p><a name=\"Short_Explanation\"><\/a><\/p>\n<h3>Short Explanation<\/h3>\n<p><a href=\"https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/aspnet_mvc.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-110 alignleft\" title=\"ASP .Net MVC3\" src=\"https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/aspnet_mvc-300x173.jpg\" alt=\"ASP .Net MVC3\" width=\"300\" height=\"173\" srcset=\"https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/aspnet_mvc-300x173.jpg 300w, https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/aspnet_mvc.jpg 550w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p><strong>Page Load Time<\/strong>\u00a0is measured using\u00a0<em><a title=\"http:\/\/www.w3schools.com\/js\/js_timing.asp\" href=\"http:\/\/www.w3schools.com\/js\/js_timing.asp\" rel=\"nofollow\">timing event<\/a><\/em>. When page is loded the variable\u00a0<em>startTime<\/em>\u00a0is set to current time [2.2]. On<em>document.ready<\/em>\u00a0event the call to\u00a0<em>pageloadDoTimer<\/em>\u00a0java script function initiate timer\u00a0<em>loopTime<\/em>. This timer executes a loop call to<em>pageloadTimerCount<\/em>\u00a0function on every 100 ms. The timer loop is canseled by calling\u00a0<em>pageloadStopTimer<\/em>\u00a0function. This call is added to all<strong>text\/html<\/strong>\u00a0or\u00a0<strong>application\/json<\/strong>\u00a0request by\u00a0<em>PerformanceMonitorModule<\/em>. Time difference betwin\u00a0<em>startTime<\/em>\u00a0and current time is &#8216;<em>Page Load Time<\/em>. The following is used to display this value:<\/p>\n<pre>  var timeMs = Math.floor((new Date() - startTime));\r\n  $('#loadtime').html(\"\" + timeMs );<\/pre>\n<p><strong>Page Generation Time<\/strong>\u00a0is measured using .NET\u2019s built-in high-resolution timer class,\u00a0<em>System.Diagnostics.Stopwatc<\/em>\u00a0in custom HTTP module (<em>PerformanceMonitorModule<\/em>). It appends performance statistics to the bottom of each page generated as a java script variable<em>pageGenerationTime<\/em>. When the\u00a0<em>pageloadStopTimer<\/em>\u00a0function is called\u00a0<em>pageGenerationTime<\/em>\u00a0value is placed in the corresponding place:<\/p>\n<pre>   $('#generatetime').html(pageGenerationTime);<\/pre>\n<p>&nbsp;<\/p>\n<h3>References<\/h3>\n<ol>\n<li id=\"cite_note-Joff2012-0\">\u00a0<a title=\"http:\/\/www.abrahamjoffe.com.au\/\" href=\"http:\/\/www.abrahamjoffe.com.au\/\" rel=\"nofollow\">Abraham Joffe<\/a>,<a title=\"http:\/\/javascriptsource.com\/text-effects\/loading-time-indicator.html\" href=\"http:\/\/javascriptsource.com\/text-effects\/loading-time-indicator.html\" rel=\"nofollow\">Loading Time<\/a>, 2012<\/li>\n<li id=\"cite_note-Hash2011-1\">\u00a0Robert Hashemian,<a title=\"http:\/\/www.hashemian.com\/tools\/page-load-time.htm\" href=\"http:\/\/www.hashemian.com\/tools\/page-load-time.htm\" rel=\"nofollow\">Indicator JavaScript Web Page Load Time<\/a>,2011<\/li>\n<li id=\"cite_note-JOBG2009-2\">\u00a0JOBG,<a title=\"http:\/\/stackoverflow.com\/questions\/1826657\/page-generation-time-asp-net-mvc\" href=\"http:\/\/stackoverflow.com\/questions\/1826657\/page-generation-time-asp-net-mvc\" rel=\"nofollow\">Page generation time &#8211; ASP.Net MVC<\/a>, Dec 1, 2009<\/li>\n<li id=\"cite_note-Sand2009-3\">\u00a0\u00a0Steven Sanderson,<a title=\"http:\/\/www.amazon.com\/Pro-ASP-NET-Framework-Steven-Sanderson\/dp\/1430210079\" href=\"http:\/\/www.amazon.com\/Pro-ASP-NET-Framework-Steven-Sanderson\/dp\/1430210079\" rel=\"nofollow\">Pro ASP.NET MVC 4 (Professional Apress)\u00a0<\/a>, April 30, 2009<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>It seems that many post concern .Net development hints do not care about the reader. That\u2019s I decided to write this blog collecting information from difference places and putting together. There are some additional helpful things from me\u2026 This post &hellip;<\/p>\n<p class=\"read-more\"><a href=\"https:\/\/blog.iordanov.info\/?p=101\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":106,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[5,21],"tags":[6,19,24,7,23,22],"class_list":["post-101","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-mvc","tag-net","tag-net-framework-4-0","tag-ajax","tag-c","tag-javascript","tag-mvc-3"],"jetpack_publicize_connections":[],"jetpack_shortlink":"https:\/\/wp.me\/p3jsZJ-1D","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack_featured_media_url":"https:\/\/blog.iordanov.info\/wp-content\/uploads\/2012\/01\/pic_1.jpg","_links":{"self":[{"href":"https:\/\/blog.iordanov.info\/index.php?rest_route=\/wp\/v2\/posts\/101","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.iordanov.info\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.iordanov.info\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.iordanov.info\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.iordanov.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=101"}],"version-history":[{"count":17,"href":"https:\/\/blog.iordanov.info\/index.php?rest_route=\/wp\/v2\/posts\/101\/revisions"}],"predecessor-version":[{"id":113,"href":"https:\/\/blog.iordanov.info\/index.php?rest_route=\/wp\/v2\/posts\/101\/revisions\/113"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.iordanov.info\/index.php?rest_route=\/wp\/v2\/media\/106"}],"wp:attachment":[{"href":"https:\/\/blog.iordanov.info\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=101"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.iordanov.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=101"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.iordanov.info\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=101"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}