首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C# DiagnosticSource

C# DiagnosticSource

作者头像
JusterZhu
发布2025-06-11 15:57:39
发布2025-06-11 15:57:39
1810
举报
文章被收录于专栏:JusterZhuJusterZhu

1. DiagnosticSource 是什么,有什么作用?

DiagnosticSource 是.NET 平台自带的诊断发布-订阅机制(发布者-监听者模式)的一部分。它允许代码组件以低耦合的方式发布诊断事件(如 HTTP 请求、数据库访问等),而外部监听者可以选择性订阅感兴趣的事件进行分析或追踪,而无需双方直接依赖于对方。

其典型作用包括:

  • 实现应用层、框架级的灵活日志采集
  • 支持 APM(应用性能监控)、分布式追踪等可观测性需求
  • 为第三方库或中间件暴露可插拔、低侵入式的诊断入口
  • 解耦业务逻辑与监控/追踪逻辑,提升模块化和测试性

2. DiagnosticSource 的优缺点

优点

  • 低入侵性:发布者与订阅者几乎完全解耦,业务代码无需关心谁在监听事件
  • 高性能:未添加监听器时几乎零开销,发布事件极为廉价
  • 强扩展性:易于集成到跨应用、跨框架的诊断系统中
  • 通用性强:不仅可用于日志和性能监控,还可用作自定义事件总线

缺点

  • 事件名称和数据结构弱类型:事件名是字符串,数据常用匿名对象,缺乏编译期检测,易出错
  • 学习曲线稍陡:理解发布/订阅模式和参数约定使新手稍感门槛
  • 调试和跟踪困难:事件流动不是强引用,可能难以排查未被订阅或数据丢失的问题

3. 适用场景

  • 框架或中间件开发:想要暴露诊断事件(数据库访问、HTTP调用等)给使用方
  • APM/日志系统接入:希望有限成本集成各类监控、性能分析、分布式链路追踪
  • 微服务、Serverless 应用:关注解耦、可插拔的事件发布和跟踪
  • 敏捷调试与分析:希望在无需修改业务代码的前提下,临时探针诊断系统行为

4. DiagnosticSource 示例代码

发布端(发布诊断事件):
代码语言:javascript
复制
using System.Diagnostics;  
  
public class Calculator  
{  
    private static readonly DiagnosticSource diagnosticSource = new DiagnosticListener("Sample.Calculator");  

    public int Add(int a, int b)  
    {  
        int result = a + b;  

        if (diagnosticSource.IsEnabled("Add"))  
        {  
            diagnosticSource.Write("Add", new { A = a, B = b, Result = result });  
        }  

        return result;  
    }  
}  
监听端(订阅并处理事件):
代码语言:javascript
复制
using System;  
using System.Diagnostics;  

public class DiagnosticListenerObserver : IObserver<DiagnosticListener>  
{  
    public void OnNext(DiagnosticListener listener)  
    {  
        // 只关注名称为 "Sample.Calculator" 的 DiagnosticListener  
        if (listener.Name == "Sample.Calculator")  
        {  
            listener.Subscribe(new DiagnosticEventObserver());  
        }  
    }  

    public void OnError(Exception error) { }  
    public void OnCompleted() { }  
}  

public class DiagnosticEventObserver : IObserver<KeyValuePair<string, object>>  
{  
    public void OnNext(KeyValuePair<string, object> value)  
    {  
        if (value.Key == "Add")  
        {  
            var payload = value.Value; // payload 是一个匿名对象  
            Console.WriteLine($"收到 Add 事件:{Newtonsoft.Json.JsonConvert.SerializeObject(payload)}");  
        }  
    }  

    public void OnError(Exception error) { }  
    public void OnCompleted() { }  
}  
启动监听和调用:
代码语言:javascript
复制
class Program  
{  
    static void Main()  
    {  
        // 注册监听 DiagnosticListener  
        var subscribe = DiagnosticListener.AllListeners.Subscribe(new DiagnosticListenerObserver());  

        var calculator = new Calculator();  
        int sum = calculator.Add(3, 5);  

        // 控制台将输出 Add 事件的详细信息  

        // 程序结束前可以取消监听(可选)  
        subscribe.Dispose();  
    }  
}  

总结

DiagnosticSource 为 .NET 开发带来了极其灵活的诊断和可观测性方法,无论你在开发库、中间件,还是希望对应用做“无感入侵”监控,都能得心应手。当然,它对类型不可知与事件命名的依赖也有一定门槛,需要明确使用约定。结合示例代码,相信你已经能掌握其核心思想并应用于实际项目之中。希望本文能帮你更深入理解和实践 DiagnosticSource!如果你喜欢这样的技术分享,欢迎点赞、评论与交流~

参考资料:

  • Microsoft 官方 DiagnosticSource 文档
  • 实现 DiagnosticSource 事件收集与监听
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JusterZhu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. DiagnosticSource 是什么,有什么作用?
  • 2. DiagnosticSource 的优缺点
    • 优点
    • 缺点
  • 3. 适用场景
  • 4. DiagnosticSource 示例代码
    • 发布端(发布诊断事件):
    • 监听端(订阅并处理事件):
    • 启动监听和调用:
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档