我想在我的应用程序中捕获某些但不是全部的HttpWebRequest流量以进行调试。它是由IIS托管的Web服务。
我看过How to: Configure Network Tracing。这很好用,但我不希望将跟踪指向文件,因为文件系统可能存在权限问题,数据敏感性等。我想直接捕获内存中的某些东西,我随后可以检查或加密和电子邮件。最好不要对app.config文件进行任何更改。
我尝试了以下内容,但显然我错过了将TextWriterTraceListener绑定到System.Net的步骤。如何将System.Net流量捕获到我的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();
编辑:具体来说,我想在运行时做相同的操作,除了我不想输出到network.log,我希望它转到我为此设置的字符串缓冲区
<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 :(得分:5)
非常感谢@LMK ,非常好。我遇到了同样的问题,因为我想记录网络流量以便在代码中进行错误分析。
使用你的VB代码,适应C#我写了这个方法:
/// <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);
}
}
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;
}
}
}
玩得开心,Marko
答案 1 :(得分:3)
您可以创建自己的TraceListener实现。我在网上找到的example(s)在运行时配置的东西没有显示使用系统跟踪源。如果你不介意弄脏手,你可以尝试使用反射切换私有静态bool System.Net.Logging.s_LoggingEnabled(。NET 2)。
以下文中的示例将其从发送电子邮件切换为发布静态事件,当您对接收跟踪消息感兴趣时可以订阅该事件:
这确实会导致性能下降,因为始终启用了日志记录(web.config中配置的全部或全部内容)。 (请参阅this article和解释删除默认跟踪以提高性能的重要性的注释。)
答案 2 :(得分:2)
以下是如何通过反射将System.Net日志记录在代码中。代码在VB中,但转换为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())
将它放在Global.asax Application_Start()中,无论你想打开什么条件。在阅读之前,您可能需要Flush()tr。