I'm looking for a way to track how long it took for a page to be generated by the server. I know I can use Trace to track this but I need a way to display this per page.
Its ASP.Net MVC 2
You can implement it like a ActionFilterAttribute
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class LoggingAttribute : ActionFilterAttribute
{
private readonly Stopwatch _sw;
public LoggingAttribute()
{
_sw = new Stopwatch();
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
_sw.Start();
Debug.WriteLine("Beginning executing: " + GetControllerAndActionName(filterContext.ActionDescriptor));
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
_sw.Stop();
var ms = _sw.ElapsedMilliseconds;
Debug.WriteLine("Finishing executing: " + GetControllerAndActionName(filterContext.ActionDescriptor));
Debug.WriteLine("Time elapsed: "+ TimeSpan.FromMilliseconds(ms).TotalSeconds);
}
private string GetControllerAndActionName(ActionDescriptor actionDescriptor)
{
return actionDescriptor.ControllerDescriptor.ControllerName + " - " + actionDescriptor.ActionName;
}
}
Decorate every controller or action-method with it and voila, it spit outs the text in debug.
EDIT: If you want to print it on the page you could add this snippet to the OnActionExecuted method
if(filterContext.Result is ViewResult) { //Make sure the request is a ViewResult, ie. a page
((ViewResult) filterContext.Result).ViewData["ExecutionTime"] = ms; //Set the viewdata dictionary
}
Now you have the executiontime saved in ViewData and can access it in the page.. I usually put it in the masterpage like this
<!-- The page took <%= ViewData["ExecutionTime"] %> ms to execute -->
Yep the Derin Suggestion is the standard Way to do it in an ASP.NEt application, i would just suggest add an if so it does not interfere with non-HTML responses: EDIT: added complete implementation
public class PerformanceMonitorModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += delegate(object sender, EventArgs e)
{
//Set Page Timer Star
HttpContext requestContext = ((HttpApplication)sender).Context;
Stopwatch timer = new Stopwatch();
requestContext.Items["Timer"] = timer;
timer.Start();
};
context.PostRequestHandlerExecute += delegate(object sender, EventArgs e)
{
HttpContext httpContext = ((HttpApplication)sender).Context;
HttpResponse response = httpContext.Response;
Stopwatch timer = (Stopwatch)httpContext.Items["Timer"];
timer.Stop();
// Don't interfere with non-HTML responses
if (response.ContentType == "text/html")
{
double seconds = (double)timer.ElapsedTicks / Stopwatch.Frequency;
string result_time = string.Format("{0:F4} sec ", seconds);
RenderQueriesToResponse(response,result_time);
}
};
}
void RenderQueriesToResponse(HttpResponse response, string result_time)
{
response.Write("<div style=\"margin: 5px; background-color: #FFFF00\"");
response.Write(string.Format("<b>Page Generated in "+ result_time));
response.Write("</div>");
}
public void Dispose() { /* Not needed */ }
}
you can also add some style to it...
And remember to register your Module in WebConfig inside httpModules Section:
<add name="Name" type="namespace, dll"/>
For a Complete Reference about this check the Pro ASP.NET MVC Framework by Steven Sanderson - Chapter 15 - Performance, Monitoring Page Generation Times.
EDIT:(comment @Pino) Here is the example for my project: alt text http://www.diarioplus.com/files/pictures/example_performance.JPG
It will depend on where you want to include this information. For example you could write an http handler that will display the render time after the </html>
tag:
public class RenderTimeModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, e) =>
{
var watch = new Stopwatch();
var app = (HttpApplication)sender;
app.Context.Items["Stopwatch"] = watch;
watch.Start();
};
context.EndRequest += (sender, e) =>
{
var app = (HttpApplication)sender;
var watch = (Stopwatch)app.Context.Items["Stopwatch"];
watch.Stop();
var ts = watch.Elapsed;
string elapsedTime = String.Format("{0} ms", ts.TotalMilliseconds);
app.Context.Response.Write(elapsedTime);
};
}
public void Dispose()
{
}
}
If you want to display render time somewhere in the middle of the html page then this render time will not account for the total page render time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With