Registrazione dei dati in Trace.axd in un file di testo / xml

Nel tentativo di rintracciare un problema di prestazioni che si verifica solo nel nostro ambiente di produzione, abbiamo abilitato la traccia all’interno dell’app, quindi consultate le chiamate ai metodi e i tempi di caricamento delle pagine.

Funziona bene e ci sono molte informazioni che aiutano a rintracciare i problemi. Tuttavia, l’unico modo per visualizzare queste informazioni è quello di accedere a Trace.axd e quindi visualizzare ogni richiesta singolarmente.

È anche ansible tracciare le prime richieste X in questo modo e X ha un limite massimo di 10.000.

C’è un modo per indirizzare queste informazioni di traccia a un file o database? Credo che questo possa essere fatto usando System.Diagnostics , tuttavia, non ho molta fortuna.

Ho abilitato la traccia usando

  

Ho provato a usare XmlWriterTraceListener usando

         

Ciò si traduce in un file xml contenente i timestamp e i dati per gli elementi di traccia come “Inizio carico”, “Fine carico”, ecc.

Tuttavia, sembra solo registrare una singola richiesta e non registra tutte le richieste. Inoltre, mentre i tempi di caricamento sono utili, idealmente mi piacerebbe avere a disposizione tutte le informazioni che possono essere viste in Trace.axd, come dati di richiesta, dati di post, dati di sessione, ecc.

È ansible tutto questo senza modifiche importanti al codice? Idealmente mi piacerebbe abilitare questo usando solo le modifiche web.config.

In alternativa, ho esaminato altre applicazioni come gli strumenti di profilatura di RedGate e Equatec, tuttavia, vorrei prima esaurire le opzioni di tracciamento non invasive.

L’applicazione è scritta in ASP.Net 3.5 e C #.

Ho un HttpModule standard che uso per tutte le mie applicazioni web per monitorare le prestazioni. Il logger utilizzato può essere modificato, inoltre può fare cose come rimuovere lo spazio bianco dalla fonte, comprimere o inviare e-mail se vengono raggiunti determinati limiti. È più facile che navigare tra le tracce di asp.net man mano che ottieni solo le informazioni che decidi essere importate.

 public class PerfHttpModule : IHttpModule { private static Common.Logging.ILog log = Common.Logging.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public static readonly string CONTEXT_RequestStart = "PerfHttpModule_RequestStart"; public static readonly string CONTEXT_RequestId = "PerfHttpModule_RequestId"; public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_BeginRequest); context.EndRequest += new EventHandler(context_EndRequest); } private void context_BeginRequest(object sender, EventArgs e) { try { if (HttpContext.Current != null) { HttpContext.Current.Items[CONTEXT_RequestStart] = DateTime.Now; HttpContext.Current.Items[CONTEXT_RequestId] = random.Next(999999).ToString("D6"); log.Info("Url: " + HttpContext.Current.Request.Url + " (" + HttpContext.Current.Request.ContentLength + ")"); } } catch { } } private void context_EndRequest(object sender, EventArgs e) { if (HttpContext.Current.Items.Contains(CONTEXT_RequestStart)) { DateTime time1 = (DateTime)HttpContext.Current.Items[CONTEXT_RequestStart]; DateTime time2 = DateTime.Now; double ms = (time2 - time1).TotalMilliseconds; log.Info("TotalMilliseconds: " + ms); if (ms > AppSettings.SlowPage || ms > AppSettings.ErrorSlowPage) { StringBuilder sb = new StringBuilder(); sb.Append("Slow page detected." + "\t"); sb.Append("TotalMilliseconds: " + ms + "\t"); sb.Append("Url: " + HttpContext.Current.Request.Url.ToString()); if (ms > AppSettings.ErrorSlowPage) { log.Error(sb.ToString()); } else if (ms > AppSettings.SlowPage) { log.Warn(sb.ToString()); } } } } } 

AGGIORNARE

  if (HttpContext.Current != null) { NameValueCollection tmp = new NameValueCollection(HttpContext.Current.Request.ServerVariables); foreach (string i in tmp.Keys) { } if (HttpContext.Current.Server != null) { if (HttpContext.Current.Server.GetLastError() != null) { } } if (HttpContext.Current.Session != null) { foreach (string i in HttpContext.Current.Session.Keys) { } } if (HttpContext.Current.Request.Cookies != null) { foreach (string i in HttpContext.Current.Request.Cookies.Keys) { } } if (HttpContext.Current.Response.Cookies != null) { foreach (string i in HttpContext.Current.Response.Cookies.Keys) { } } if (HttpContext.Current.Items != null) { foreach (string i in HttpContext.Current.Items.Keys) { } } if (HttpContext.Current.Request.Form != null) { foreach (string i in HttpContext.Current.Request.Form.Keys) { } } } 

I dati di traccia sono coperti da un DataSet standard. Non puoi prenderlo ufficialmente in possesso, ma qui c’è un trucco che può farlo (sembra funzionare su .NET da 2 a 4):

 public static DataSet GetTraceData(Page page) { if (page == null) throw new ArgumentNullException("page"); return (DataSet)typeof(TraceContext).GetField("_requestData", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(page.Trace); } 

Una volta che hai il DataSet, puoi fare tutto ciò che vuoi con esso, salvare in un file XML (DataSet.WriteXml), uno stream, ecc.

Ovviamente, poiché utilizza un campo interno, potrebbe non essere supportato in futuro.