为什么.NET Framework应用中无法订阅HttpHandlerDiagnosticListener
解决方案
- 开启.NET Framework下的Activity传播开关
传统ASP.NET默认不会触发HttpHandlerDiagnosticListener相关事件,需要在web.config的<appSettings>节点下添加配置:
同时确认<add key="System.Net.Http.EnableActivityPropagation" value="true" />system.web节点下的运行时目标框架配置正确:<httpRuntime targetFramework="4.7.2" /> <compilation targetFramework="4.7.2" /> - 处理程序集绑定重定向冲突
首先安装官方System.Net.Http NuGet包,不要使用.NET Framework自带的原生System.Net.Http程序集,原生版本不支持DiagnosticSource事件输出。所有相关包安装完成后,确认web.config的<runtime><assemblyBinding>节点下存在正确的绑定重定向,版本统一指向你使用的包版本,示例如下:<dependentAssembly> <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.7.0" newVersion="4.0.7.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" /> </dependentAssembly> - 避免订阅对象被GC回收
你当前的代码没有存储Subscribe方法返回的IDisposable对象,订阅逻辑会随时被GC回收导致后续收不到事件,需要用静态变量持有订阅引用,修改后的代码如下:// 全局静态变量持有订阅引用,避免被GC回收 private static IDisposable _allListenerSub; private static IDisposable _httpHandlerSub; // 放在Global.asax的Application_Start方法最开始执行 _allListenerSub = DiagnosticListener.AllListeners.Subscribe(listener => { if (listener.Name == "HttpHandlerDiagnosticListener") { _httpHandlerSub = listener.Subscribe(diagnostic => { if (diagnostic.Key == "System.Net.Http.HttpRequestOut.Start") { // 自定义逻辑 } else if (diagnostic.Key == "System.Net.Http.HttpRequestOut.Stop") { // 自定义逻辑 } }); } }); - 调整订阅执行时机
订阅逻辑必须放在Application_Start方法的最开始执行,晚于任何HttpClient实例初始化、中间件注册逻辑都会导致漏掉事件。
内容的提问来源于stack exchange,提问作者Michiel van Oosterhout
相关产品推荐
相关产品推荐

