Traccia System.Net (HttpWebRequest) senza utilizzare file o app.config?

Voglio catturare determinati, ma non tutti, il traffico HttpWebRequest nella mia applicazione per scopi di debug. È un servizio web ospitato da IIS.

Ho letto come: Configura traccia di rete . Funziona alla grande, ma non voglio dirigere la traccia su un file, a causa di possibili problemi di authorization sul file system, sensibilità dei dati, ecc. Vorrei acquisire direttamente un qualcosa in memoria che posso successivamente controllare o crittografare e inviare per e-mail. Preferibilmente, questo non comporterebbe alcuna modifica al file app.config.

Ho provato quanto segue, ma ovviamente mi manca un passaggio per bind TextWriterTraceListener in System.Net. Come posso catturare il traffico System.Net nel mio StringWriter?

StringWriter sw = new StringWriter(); TextWriterTraceListener myListener = new TextWriterTraceListener(sw); Trace.Listeners.Add(myListener); HttpWebRequest req = (HttpWebRequest) WebRequest.Create("http://www.microsoft.com"); HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); Stream s = resp.GetResponseStream(); byte[] buf = new byte[4096]; while (s.Read(buf, 0, buf.Length) > 0) ; s.Close(); myListener.Flush(); sw.Flush(); 

Modifica: Specificamente, voglio fare l’equivalente di questo al runtime, tranne che non voglio che l’output passi a network.log, voglio che vada ad un buffer di stringa che ho impostato per questo scopo.

                

Grazie mille @ LMK , è carino. Ho avuto lo stesso problema, perché voglio registrare il traffico di rete per l’analisi degli errori nel codice.

Con il tuo codice VB, adattato a C # ho scritto questo metodo:

 ///  /// Executes a action with enabled System.Net.Logging with listener(s) at the code-site /// /// Message from Microsoft: /// To configure you the listeners and level of logging for a listener you need a reference to the listener that is going to be doing the tracing. /// A call to create a new TraceSource object creates a trace source with the same name as the one used by the System.Net.Sockets classs, /// but it's not the same trace source object, so any changes do not have an effect on the actual TraceSource object that System.Net.Sockets is using. ///  /// The sourceLevel for the System.Net traceSource /// The sourceLevel for the System.Net.HttpListener traceSource /// The sourceLevel for the System.Net.Sockets traceSource /// The sourceLevel for the System.Net.Cache traceSource /// The action to execute /// The listener(s) to use public static void ExecuteWithEnabledSystemNetLogging(SourceLevels webTraceSourceLevel, SourceLevels httpListenerTraceSourceLevel, SourceLevels socketsTraceSourceLevel, SourceLevels cacheTraceSourceLevel, Action actionToExecute, params TraceListener[] listener) { if (listener == null) { throw new ArgumentNullException("listener"); } if (actionToExecute == null) { throw new ArgumentNullException("actionToExecute"); } var logging = typeof(WebRequest).Assembly.GetType("System.Net.Logging"); var isInitializedField = logging.GetField("s_LoggingInitialized", BindingFlags.NonPublic | BindingFlags.Static); if (!(bool)isInitializedField.GetValue(null)) { //// force initialization HttpWebRequest.Create("http://localhost"); Thread waitForInitializationThread = new Thread(() => { while (!(bool)isInitializedField.GetValue(null)) { Thread.Sleep(100); } }); waitForInitializationThread.Start(); waitForInitializationThread.Join(); } var isEnabledField = logging.GetField("s_LoggingEnabled", BindingFlags.NonPublic | BindingFlags.Static); var webTraceSource = (TraceSource)logging.GetField("s_WebTraceSource", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); var httpListenerTraceSource = (TraceSource)logging.GetField("s_HttpListenerTraceSource", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); var socketsTraceSource = (TraceSource)logging.GetField("s_SocketsTraceSource", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); var cacheTraceSource = (TraceSource)logging.GetField("s_CacheTraceSource", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); bool wasEnabled = (bool)isEnabledField.GetValue(null); Dictionary originalTraceSourceFilters = new Dictionary(); //// save original Levels var originalWebTraceSourceLevel = webTraceSource.Switch.Level; var originalHttpListenerTraceSourceLevel = httpListenerTraceSource.Switch.Level; var originalSocketsTraceSourceLevel = socketsTraceSource.Switch.Level; var originalCacheTraceSourceLevel = cacheTraceSource.Switch.Level; //System.Net webTraceSource.Listeners.AddRange(listener); webTraceSource.Switch.Level = SourceLevels.All; foreach (TraceListener tl in webTraceSource.Listeners) { if (!originalTraceSourceFilters.ContainsKey(tl)) { originalTraceSourceFilters.Add(tl, tl.Filter); tl.Filter = new ModifiedTraceFilter(tl, originalWebTraceSourceLevel, webTraceSourceLevel, originalHttpListenerTraceSourceLevel, httpListenerTraceSourceLevel, originalSocketsTraceSourceLevel, socketsTraceSourceLevel, originalCacheTraceSourceLevel, cacheTraceSourceLevel, listener.Contains(tl)); } } //System.Net.HttpListener httpListenerTraceSource.Listeners.AddRange(listener); httpListenerTraceSource.Switch.Level = SourceLevels.All; foreach (TraceListener tl in httpListenerTraceSource.Listeners) { if (!originalTraceSourceFilters.ContainsKey(tl)) { originalTraceSourceFilters.Add(tl, tl.Filter); tl.Filter = new ModifiedTraceFilter(tl, originalWebTraceSourceLevel, webTraceSourceLevel, originalHttpListenerTraceSourceLevel, httpListenerTraceSourceLevel, originalSocketsTraceSourceLevel, socketsTraceSourceLevel, originalCacheTraceSourceLevel, cacheTraceSourceLevel, listener.Contains(tl)); } } //System.Net.Sockets socketsTraceSource.Listeners.AddRange(listener); socketsTraceSource.Switch.Level = SourceLevels.All; foreach (TraceListener tl in socketsTraceSource.Listeners) { if (!originalTraceSourceFilters.ContainsKey(tl)) { originalTraceSourceFilters.Add(tl, tl.Filter); tl.Filter = new ModifiedTraceFilter(tl, originalWebTraceSourceLevel, webTraceSourceLevel, originalHttpListenerTraceSourceLevel, httpListenerTraceSourceLevel, originalSocketsTraceSourceLevel, socketsTraceSourceLevel, originalCacheTraceSourceLevel, cacheTraceSourceLevel, listener.Contains(tl)); } } //System.Net.Cache cacheTraceSource.Listeners.AddRange(listener); cacheTraceSource.Switch.Level = SourceLevels.All; foreach (TraceListener tl in cacheTraceSource.Listeners) { if (!originalTraceSourceFilters.ContainsKey(tl)) { originalTraceSourceFilters.Add(tl, tl.Filter); tl.Filter = new ModifiedTraceFilter(tl, originalWebTraceSourceLevel, webTraceSourceLevel, originalHttpListenerTraceSourceLevel, httpListenerTraceSourceLevel, originalSocketsTraceSourceLevel, socketsTraceSourceLevel, originalCacheTraceSourceLevel, cacheTraceSourceLevel, listener.Contains(tl)); } } isEnabledField.SetValue(null, true); try { actionToExecute(); } finally { //// restore Settings webTraceSource.Switch.Level = originalWebTraceSourceLevel; httpListenerTraceSource.Switch.Level = originalHttpListenerTraceSourceLevel; socketsTraceSource.Switch.Level = originalSocketsTraceSourceLevel; cacheTraceSource.Switch.Level = originalCacheTraceSourceLevel; foreach (var li in listener) { webTraceSource.Listeners.Remove(li); httpListenerTraceSource.Listeners.Remove(li); socketsTraceSource.Listeners.Remove(li); cacheTraceSource.Listeners.Remove(li); } //// restore filters foreach (var kvP in originalTraceSourceFilters) { kvP.Key.Filter = kvP.Value; } isEnabledField.SetValue(null, wasEnabled); } } 

La class ModifiedTraceFilter:

 public class ModifiedTraceFilter : TraceFilter { private readonly TraceListener _traceListener; private readonly SourceLevels _originalWebTraceSourceLevel; private readonly SourceLevels _originalHttpListenerTraceSourceLevel; private readonly SourceLevels _originalSocketsTraceSourceLevel; private readonly SourceLevels _originalCacheTraceSourceLevel; private readonly SourceLevels _modifiedWebTraceTraceSourceLevel; private readonly SourceLevels _modifiedHttpListenerTraceSourceLevel; private readonly SourceLevels _modifiedSocketsTraceSourceLevel; private readonly SourceLevels _modifiedCacheTraceSourceLevel; private readonly bool _ignoreOriginalSourceLevel; private readonly TraceFilter _filter = null; public ModifiedTraceFilter(TraceListener traceListener, SourceLevels originalWebTraceSourceLevel, SourceLevels modifiedWebTraceSourceLevel, SourceLevels originalHttpListenerTraceSourceLevel, SourceLevels modifiedHttpListenerTraceSourceLevel, SourceLevels originalSocketsTraceSourceLevel, SourceLevels modifiedSocketsTraceSourceLevel, SourceLevels originalCacheTraceSourceLevel, SourceLevels modifiedCacheTraceSourceLevel, bool ignoreOriginalSourceLevel) { _traceListener = traceListener; _filter = traceListener.Filter; _originalWebTraceSourceLevel = originalWebTraceSourceLevel; _modifiedWebTraceTraceSourceLevel = modifiedWebTraceSourceLevel; _originalHttpListenerTraceSourceLevel = originalHttpListenerTraceSourceLevel; _modifiedHttpListenerTraceSourceLevel = modifiedHttpListenerTraceSourceLevel; _originalSocketsTraceSourceLevel = originalSocketsTraceSourceLevel; _modifiedSocketsTraceSourceLevel = modifiedSocketsTraceSourceLevel; _originalCacheTraceSourceLevel = originalCacheTraceSourceLevel; _modifiedCacheTraceSourceLevel = modifiedCacheTraceSourceLevel; _ignoreOriginalSourceLevel = ignoreOriginalSourceLevel; } public override bool ShouldTrace(TraceEventCache cache, string source, TraceEventType eventType, int id, string formatOrMessage, object[] args, object data1, object[] data) { SourceLevels originalTraceSourceLevel = SourceLevels.Off; SourceLevels modifiedTraceSourceLevel = SourceLevels.Off; if (source == "System.Net") { originalTraceSourceLevel = _originalWebTraceSourceLevel; modifiedTraceSourceLevel = _modifiedWebTraceTraceSourceLevel; } else if (source == "System.Net.HttpListener") { originalTraceSourceLevel = _originalHttpListenerTraceSourceLevel; modifiedTraceSourceLevel = _modifiedHttpListenerTraceSourceLevel; } else if (source == "System.Net.Sockets") { originalTraceSourceLevel = _originalSocketsTraceSourceLevel; modifiedTraceSourceLevel = _modifiedSocketsTraceSourceLevel; } else if (source == "System.Net.Cache") { originalTraceSourceLevel = _originalCacheTraceSourceLevel; modifiedTraceSourceLevel = _modifiedCacheTraceSourceLevel; } var level = ConvertToSourceLevel(eventType); if (!_ignoreOriginalSourceLevel && (originalTraceSourceLevel & level) == level) { if (_filter == null) { return true; } else { return _filter.ShouldTrace(cache, source, eventType, id, formatOrMessage, args, data1, data); } } else if (_ignoreOriginalSourceLevel && (modifiedTraceSourceLevel & level) == level) { if (_filter == null) { return true; } else { return _filter.ShouldTrace(cache, source, eventType, id, formatOrMessage, args, data1, data); } } return false; } private static SourceLevels ConvertToSourceLevel(TraceEventType eventType) { switch (eventType) { case TraceEventType.Critical: return SourceLevels.Critical; case TraceEventType.Error: return SourceLevels.Error; case TraceEventType.Information: return SourceLevels.Information; case TraceEventType.Verbose: return SourceLevels.Verbose; case TraceEventType.Warning: return SourceLevels.Warning; default: return SourceLevels.ActivityTracing; } } } 

Buon divertimento, Marko

È ansible creare la propria implementazione TraceListener. Gli esempi che ho trovato online che configurano le cose in fase di esecuzione non mostrano il funzionamento con le origini di traccia del sistema. Se non ti dispiace sporcarti le mani potresti provare a usare reflection per triggersre il bool statico privato System.Net.Logging.s_LoggingEnabled (.NET 2).

Prendi l’esempio nel seguente articolo e passa dall’invio di e-mail alla pubblicazione di un evento statico a cui puoi iscriverti quando sei interessato a ricevere messaggi di tracciamento:

Estensione di System.Diagnostics

Ciò provoca un impatto sulle prestazioni poiché la registrazione è abilitata ininterrottamente (tutto o niente come configurato nel web.config). (Consulta questo articolo e i commenti che spiegano l’importanza della rimozione della traccia predefinita per migliorare le prestazioni.)

Ecco come colbind System.Net per l’accesso al codice tramite riflessione. Il codice è in VB ma è banale da convertire in c # …

 Dim logging = GetType(Net.HttpWebRequest).Assembly.GetType("System.Net.Logging") Dim enabled = logging.GetField("s_LoggingEnabled", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static) enabled.SetValue(Nothing, True) Dim webTr = logging.GetProperty("Web", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static) Dim tr as TraceSource = webTr.GetValue(Nothing, Nothing) tr.Switch.Level = SourceLevels.Verbose tr.Listeners.Add(New MyTraceListener()) 

Metti questo in Global.asax Application_Start () con qualsiasi condizione tu voglia accenderlo. Potrebbe essere necessario Lavare () tr prima di leggere.