2009-12-01 26 views
15

Estoy buscando una manera de rastrear cuánto tiempo tardó en generar una página el servidor. Sé que puedo usar Trace para rastrear esto, pero necesito una forma de mostrar esto por página.Tiempo de generación de página - ASP.Net MVC

Su ASP.Net MVC 2

Respuesta

14

sí Derin la sugerencia es la forma estándar de hacerlo en una aplicación ASP.NEt, sólo sugeriría añadir un caso por lo que no interfiere con las respuestas que no sean HTML: EDITAR: se agregó implementación completa ión

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 */ } 
} 

también se puede añadir un poco de estilo a ella ...

Y recuerda que para registrar su módulo de WebConfig dentro httpModules Sección:

<add name="Name" type="namespace, dll"/> 

Para una referencia completa sobre este comprobar el Pro ASP.NET MVC Framework por Steven Sanderson - Capítulo 15 - Performance, Monitoring Page Generation Times.

EDIT: (comentario @Pino) ​​ Aquí está el ejemplo de mi proyecto:? alt text http://www.diarioplus.com/files/pictures/example_performance.JPG

+0

Gracias - funciona bien, excepto Esto parece dar salida DESPUÉS del elemento que rompe mi página :(sugerencias? – LiamB

+0

Esto se agrega (se agrega) como parte de la respuesta, puede no ser después de la etiqueta de cierre HTML. – JOBG

+0

Edito mi publicación con un img de ejemplo, ya tengo un proyecto en ejecución y lo pruebo, no sé por qué Darin dijo que después del HTML ..., tal vez se refirió a otra implementación. – JOBG

4

Esto dependerá de donde desea incluir esta información. Por ejemplo, usted podría escribir un controlador HTTP que mostrará el tiempo de render después de la </html> etiqueta:

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() 
    { 
    } 
} 

Si desea mostrar el tiempo de render en algún lugar en el medio de la página HTML, entonces este tiempo de render no va a dar cuenta de la tiempo total de renderizado de página

+0

Esto parece salida después del elemento que se rompe mi página de sugerencias :( – LiamB

+0

Sí, eso es lo que he dicho en mi Puede ponerlo en un comentario si no quiere romper su validación. –

+0

¿Funcionará este enfoque con los resultados de Json y File o solo html? –

15

Se puede implementar como un 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; 
    } 
} 

Decorar cada controlador o acción-método con él y listo, se escupió outs en el texto de depuración.

EDIT: Si desea imprimir en la página podría agregar este fragmento con el método OnActionExecuted

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 
} 

Ahora usted tiene un ExecutionTime guardado en ViewData y puede acceder a él en la página .. Por lo general ponerlo en el masterpage como esto

<!-- The page took <%= ViewData["ExecutionTime"] %> ms to execute --> 
+0

Decorar cada controlador o método de acción es un poco doloroso ya que tener mucho (proyecto bastante grande) - de todos modos podemos hacer que esto funcione en todo el sitio sin hacer un cambio tan grande? – LiamB

+3

En mi proyecto, todos mis controladores heredan de un controlador de base . Así que simplemente decore el controlador de base, que a su vez "decora" todos los métodos de acción que se están ejecutando. –

+2

Su enfoque bastante bueno, solo vale la pena mencionar que esto realmente rastrea el tiempo de vida del controlador, y no el tiempo de vida total de la solicitud. – JOBG

Cuestiones relacionadas