Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I display the duration it took to generate a page in a pages footer?

During debug builds I would like to show the duration it took, server side, to generate a page in the pages footer.

So for example if a page takes 250ms server side I would like that displayed in the footer, in debug builds. How can I achieve this in an ASP.NET MVC project?

like image 586
Sam Saffron Avatar asked Jun 14 '10 07:06

Sam Saffron


2 Answers

Add this to the footer in your master page:

Page rendering took <%= DateTime.Now.Subtract( this.ViewContext.HttpContext.Timestamp ).TotalMilliseconds.ToString() %>

You can also wrap this in an extension method:

public static class Extensions
{
  public static string RequestDurationinMs( this HtmlHelper helper )
  {
    #if DEBUG
    return DateTime.Now.Subtract( helper.ViewContext.HttpContext.Timestamp ).TotalMilliseconds.ToString();
    #endif
  }
}

Use that like this:

<%= Html.RequestDurationinMs() %>

You may need to import the namespace of the extensions class: <%@ Import Namespace="Your.Namespace" %>

like image 72
Marnix van Valen Avatar answered Oct 23 '22 03:10

Marnix van Valen


The ViewContext.HttpContext.Timestamp thing as suggested by Marnix is clever, I hadn't realised that was there. However, you could also do it as an HttpModule which would work in non MVC application too:

using System;
using System.Web;

namespace MyLibrary
{
    public class PerformanceMonitorModule : IHttpModule
    {
        public void Dispose() { }

        public void Init(HttpApplication context)
        {
            context.PreSendRequestContent += delegate(object sender, EventArgs e)
            {
                HttpContext httpContext = ((HttpApplication)sender).Context;
                if (httpContext.Response.ContentType == "text/html")
                {
                    DateTime timestamp = httpContext.Timestamp;

                    double seconds = (double)DateTime.Now.Subtract(timestamp).Ticks / (double)TimeSpan.TicksPerSecond;
                    string result = String.Format("{0:F4} seconds ({1:F0} req/sec)", seconds, 1 / seconds);

                    httpContext.Response.Write("<div style=\"position: fixed; right: 5px; bottom: 5px; font-size: 15px; font-weight: bold;\">Page Execution Time: " + result + "</div>");
                }
            };
        }
    }
}

Then put this into your web.config:

<httpModules>
    <!-- Other httpModules (snip) -->

    <add name="PerformanceMonitor" type="MyLibrary.PerformanceMonitorModule, MyLibrary"/>
</httpModules>

This will record the time at the very last moment it gets before sending the HTML content to the browser so that it is measuring as much of the HTTP pipeline as possible. Not sure if sticking ViewContext.HttpContext.Timestamp in the page markup can achieve this?

Note: this won't produce valid HTML markup because it spits a <div> to the bottom of the page, so only use for development/performance analysis.

EDIT: I modified the HttpModule to use HttpContext.Timestamp instead of storing a Stopwatch object in the Request context, as it seems to give more accurate results.

like image 44
Sunday Ironfoot Avatar answered Oct 23 '22 05:10

Sunday Ironfoot