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 --> Application_Start handler to avoid decorating every class/action with it.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.