2009-12-01 14 views
15

Sto cercando un modo per tenere traccia del tempo necessario alla generazione di una pagina da parte del server. So che posso usare Trace per tracciare questo, ma ho bisogno di un modo per visualizzare questo per pagina.Tempo di generazione della pagina - ASP.Net MVC

sua ASP.Net MVC 2

risposta

14

Yep la Derin suggestione è il modo standard per farlo in un'applicazione ASP.NEt, vorrei solo suggerire aggiungere un caso in modo da non interferire con le risposte non HTML: MODIFICA: aggiunto implementat completo ione

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

si può anche aggiungere un po 'di stile ad esso ...

E ricordatevi di registrare il modulo in WebConfig all'interno httpModules Sezione:

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

Per un riferimento completo su questo controllare la Pro ASP.NET MVC Framework di Steven Sanderson - Capitolo 15 - Prestazioni, tempi di generazione delle pagine di monitoraggio.

EDIT: (commento @Pino) ​​ Ecco l'esempio per il mio progetto:? alt text http://www.diarioplus.com/files/pictures/example_performance.JPG

+0

Grazie - funziona bene eccetto che sembra uscita DOPO l'elemento che interrompe la mia pagina :(suggerimenti? – LiamB

+0

Questo è aggiunto (accoda) come parte della risposta, potrebbe non essere dopo il tag di chiusura HTML – JOBG

+0

Ho modificato il mio post con un esempio img, ho già un progetto in esecuzione e testarlo, non so perché Darin ha detto che è dopo l'HTML ..?, forse si è riferito a un'altra implementazione. – JOBG

4

Dipenderà da dove si desidera includere queste informazioni. Per esempio si potrebbe scrivere un gestore HTTP che visualizza il tempo di rendering dopo il </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() 
    { 
    } 
} 

Se si desidera visualizzare il tempo di rendering qualche parte nel mezzo della pagina html, allora questa volta non rappresenteranno il render tempo di rendering della pagina totale.

+0

Questo sembra uscita dopo l'elemento che rompe la mia pagina :(suggerimenti – LiamB

+0

Sì, è quello che ho detto nel mio post. Potresti inserirlo in un commento se non vuoi interrompere la convalida. –

+0

Questo approccio funziona con i risultati di JSON e File o semplicemente html? –

15

È possibile implementare come 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; 
    } 
} 

Decorare ogni controller o l'azione metodo con esso e voilà, è sputare out il testo di debug.

EDIT: Se si desidera stampare sulla pagina è possibile aggiungere questo frammento di codice al metodo 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 
} 

Ora avete l'ExecutionTime salvato in Viewdata e può accedere nella pagina .. io di solito metterlo nel masterpage come questo

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

Decorare ogni controller o metodo di azione è un po 'un problema molto (progetto abbastanza grande) - comunque possiamo rendere questo sito di lavoro senza apportare cambiamenti così grandi? – LiamB

+3

Nel mio progetto tutti i miei controller ereditano da un BaseController . Quindi ho appena decorato il basecontroller, che a sua volta "decora" tutti i metodi d'azione che vengono eseguiti. –

+2

È un approccio abbastanza buono, vale la pena ricordare che questo in realtà tiene traccia del tempo di vita del Controller e non del tempo di vita totale richiesto. – JOBG

Problemi correlati