2009-06-26 15 views
10

Quiero capturar cierto, pero no todo, tráfico HttpWebRequest en mi aplicación para fines de depuración. Es un servicio web alojado por IIS.Seguimiento de System.Net (HttpWebRequest) sin usar archivos o app.config?

He leído How to: Configure Network Tracing. Esto funciona muy bien, pero no quiero dirigir el rastreo a un archivo, debido a posibles problemas de permisos en el sistema de archivos, sensibilidad a los datos, etc. Me gustaría capturar directamente algo en la memoria que luego pueda inspeccionar o encriptar y enviar por correo electrónico. Preferiblemente, esto no implicaría ningún cambio en el archivo app.config.

Intenté lo siguiente, pero obviamente me falta un paso para unir el TextWriterTraceListener en System.Net. ¿Cómo puedo capturar el tráfico de System.Net en mi 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(); 

Editar: En concreto, quiero hacer el equivalente de esto en tiempo de ejecución, excepto que no quiero ir a la salida a network.log, yo quiero que vaya a un búfer de cadena que he establecido para este propósito

<configuration> 

<system.diagnostics> 

<sources> 
    <source name="System.Net.Sockets" tracemode="includehex"> 
    <listeners> 
     <add name="System.Net.Sockets" type="System.Diagnostics.TextWriterTraceListener" initializeData="network.log" /> 
    </listeners> 
    </source> 
</sources> 

<switches> 
    <add name="System.Net.Sockets" value="Verbose"/> 
</switches> 

<trace autoflush="true" /> 
</system.diagnostics> 
</configuration> 
+0

http: // vbcity. com/forums/topic.asp? tid = 140182 está pidiendo lo mismo. La respuesta de Microsoft es ciertamente desalentadora. –

Respuesta

3

Puede crear su propia implementación de TraceListener. El example (s) que he encontrado en línea que configura cosas en tiempo de ejecución no muestra el trabajo con las fuentes de rastreo del sistema. Si no le molesta ensuciarse las manos, intente usar el reflejo para alternar el bool estático privado System.Net.Logging.s_LoggingEnabled (.NET 2).

Tomemos el ejemplo en el siguiente artículo y cambiar desde el envío de correos electrónicos a la publicación de un evento estático que puede suscribirse a cuando estás interesado en recibir mensajes de seguimiento:

Extending System.Diagnostics

Esto hace causar un golpe de rendimiento ya que el registro está habilitado todo el tiempo (todo o nada como configurado en el web.config). (Consulte this article y comentarios que expliquen la importancia de eliminar la traza predeterminada para mejorar el rendimiento.)

2

Aquí se explica cómo conectar el registro de System.Net en código a través de la reflexión. Es el código de VB, pero es trivial para convertir a 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()) 

poner esto en Global.asax Application_Start() con cualquier condición que desea activarlo. Es posible que necesite enjuagar() tr antes de leer.

4

Gracias grandes @LMK, eso es bueno. Tuve el mismo problema, porque quiero registrar el tráfico de red para el análisis de errores en el código.

Con su VB-Code, adaptada a C# he escrito este método:

/// <summary> 
/// 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 classes, 
/// 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. 
/// </summary> 
/// <param name="webTraceSourceLevel">The sourceLevel for the System.Net traceSource</param> 
/// <param name="httpListenerTraceSourceLevel">The sourceLevel for the System.Net.HttpListener traceSource</param> 
/// <param name="socketsTraceSourceLevel">The sourceLevel for the System.Net.Sockets traceSource</param> 
/// <param name="cacheTraceSourceLevel">The sourceLevel for the System.Net.Cache traceSource</param> 
/// <param name="actionToExecute">The action to execute</param> 
/// <param name="listener">The listener(s) to use</param> 
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<TraceListener, TraceFilter> originalTraceSourceFilters = new Dictionary<TraceListener, TraceFilter>(); 

    //// 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); 
    } 
} 

El ModifiedTraceFilter clase:

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; 
     } 
    } 
} 

divertirse, Marko

Cuestiones relacionadas