首页 > 其他分享 >DiagnosticSource DiagnosticListener 无侵入式分布式跟踪

DiagnosticSource DiagnosticListener 无侵入式分布式跟踪

时间:2024-03-14 09:24:07浏览次数:24  
标签:void DiagnosticListener value cEvent activity public DiagnosticSource 分布式

ASP.NET Core 中的框架中发出大量诊断事件,包括当前请求进入请求完成事件,HttpClient发出收到与响应,EFCore查询等等。

我们可以利用DiagnosticListener来选择性地监听这些事件,然后通过自己的方式组织这些日志,实现无侵入的分布式跟踪。

下面我们通过DiagnosticSource监听EFCore,与HTTPClient,实现链路追踪。

创建监听

现在我们将配置一个DiagnosticListener来监听全部事件。 

首先,我们需要一个IObserver<DiagnosticListener>,我们将使用它来订阅所有事件。

public class TestDiagnosticObserver : IObserver<DiagnosticListener>
{
    public void OnNext(DiagnosticListener value)
    {
        value.Subscribe(new TestKeyValueObserver());
    }
    public void OnCompleted() { }
    public void one rror(Exception error) { }
}
  其中重要的方法是OnNext。 然后我们传入另一个自定义类型TestKeyValueObserver,这是实际接收实例发出的事件的类DiagnosticListener。 该事件会接受KeyValuePair<string, object>参数,我们后续可针对此参数做业务相关的筛选。
public class TestKeyValueObserver : IObserver<KeyValuePair<string, object?>>
{
    public void OnNext(KeyValuePair<string, object?> value)
    {
        var activity = Activity.Current;

        Console.WriteLine($"traceId {activity?.TraceId} Received event: {value.Key}");
    }
    public void OnCompleted() { }
    public void one rror(Exception error) { }
}

 

最后一步是在应用程序中注册我们的程序TestDiagnosticObserver。

DiagnosticListener.AllListeners.Subscribe(new TestDiagnosticObserver());

 

创建HTTP请求与EFCore查询

我们新建一个接口,用来集成EF与HttpClient。并调用这个接口查看DiagnosticListener 监听到的内容

[HttpGet]
public async Task<string> GetAsync()
{
    //HTTP
    await _httpClient.GetAsync("https://www.baidu.com");

    //EF
    Item item = new Item()
    {
        Barcode = Guid.NewGuid().ToString(),
        Brand = "Milky Way",
        Name = "Milk",
        PruchasePrice = 20.5,
        SellingPrice = 25.5
    };
    _productsContext.Items.Add(item);
    _productsContext.SaveChanges();
    return "OK";
}

 

调用此接口来看看我们的DiagnosticListener的效果。

可以看到收到了很多Event,包括当前请求的各个阶段,HttpClient的各个阶段,与EFCore查询的各个阶段。

 

解析Event

然后修改TestKeyValueObserver,我们从中挑选我们需要的HTTPClient与EFCore相关的事件。

public class TestKeyValueObserver : IObserver<KeyValuePair<string, object?>>
{
    public void OnNext(KeyValuePair<string, object?> value)
    {
        var activity = Activity.Current;

        //Console.WriteLine($"traceId {activity?.TraceId} Received event: {value.Key}");
        if (value.Key.StartsWith("System.Net.Http.Request"))
        {
            var cEventStr = JsonConvert.SerializeObject(value.Value);
            var cEvent = JsonConvert.DeserializeAnonymousType(cEventStr, new { Request = new { RequestUri = ""} , Timestamp = 2879029490722 });
            Console.WriteLine($"traceId {activity?.TraceId} Request.Start: {cEvent.Timestamp} ");
            Console.WriteLine($"traceId {activity?.TraceId} Request.Uri: {cEvent.Request.RequestUri} ");
        }
        if (value.Key.StartsWith("System.Net.Http.Response"))
        {
            var cEventStr = JsonConvert.SerializeObject(value.Value);
            var cEvent = JsonConvert.DeserializeAnonymousType(cEventStr, new { Request = new { RequestUri = "" }, Timestamp = 2879029490722 });
            Console.WriteLine($"traceId {activity?.TraceId} Http.Response: {cEvent.Timestamp} ");
        }


        if (value.Key.StartsWith("Microsoft.EntityFrameworkCore.Database.Connection.ConnectionOpening"))
        {
            var cEvent = (Microsoft.EntityFrameworkCore.Diagnostics.ConnectionEventData)value.Value;
            Console.WriteLine($"traceId {activity?.TraceId} Connection.ConnectionOpening: {cEvent?.StartTime.ToString("yyyy-MM-dd HH:mm:ss:fff")} ");
        }
        if (value.Key.StartsWith("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting"))
        {
            var cEvent = (Microsoft.EntityFrameworkCore.Diagnostics.CommandEventData)value.Value;
            Console.WriteLine($"traceId {activity?.TraceId}  {cEvent?.Command.CommandText} ");
        }
        if (value.Key.StartsWith("Microsoft.EntityFrameworkCore.Database.Connection.ConnectionClosed"))
        {
            var cEvent = (Microsoft.EntityFrameworkCore.Diagnostics.ConnectionEventData)value.Value;
            Console.WriteLine($"traceId {activity?.TraceId} Connection.ConnectionClosed: {cEvent?.StartTime.ToString("yyyy-MM-dd HH:mm:ss:fff")} ");
        }
    }
    public void OnCompleted() { }
    public void one rror(Exception error) { }
}

 

再次启动,查看效果,可以看到已经获取到了http请求的开始结束事件,EF的查询语句,开始事件等。

 

最后我们可以结构化这些数据,并将其持久化到自己的监控体系中,实现链路跟踪。

标签:void,DiagnosticListener,value,cEvent,activity,public,DiagnosticSource,分布式
From: https://www.cnblogs.com/chenyishi/p/18071178

相关文章

  • 一致性哈希算法及其在分布式系统中的应用
    摘要本文将会从实际应用场景出发,介绍一致性哈希算法(ConsistentHashing)及其在分布式系统中的应用。首先本文会描述一个在日常开发中经常会遇到的问题场景,借此介绍一致性哈希算法以及这个算法如何解决此问题;接下来会对这个算法进行相对详细的描述,并讨论一些如虚拟节点等与此算......
  • 考虑功率均分与电压频率的事件触发分布式二次控制MATLAB模型
    微❤关注“电气仔推送”获得资料(专享优惠)模型简介此模型是在《基于事件触发机制的孤岛微电网二次电压与频率协同控制MATLAB仿真模型》上进一步创作的,之前的模型只考虑了二次电压与频率控制,并没有考虑均分这一项点。因此此模型在事件触发机制的基础上,继续创作了基于事件触发......
  • Seata:实现分布式事务的利器
    Seata:实现分布式事务的利器Seata是一种开源的分布式事务解决方案,旨在解决分布式系统中的事务一致性问题。本文将介绍Seata的概念和原理,探讨其在分布式应用程序中的应用场景,并讨论其对于构建可靠的分布式系统的重要性。Seata的概念和原理分布式事务:在分布式系统中,事务的执......
  • HADOOP完全分布式搭建(饭制版)
    HADOOP完全分布式搭建(饭制版)1.虚拟机安装安装系统点击VMwareWorkstation左上角文件,新建虚拟机选择自定义,点击下一步点击下一步选择稍后安装操作系统(后续我们使用的操作系统为CentOS7),点击下一步客户机系统选择Linux,版本选择CentOS764位,点击下一步自定义安......
  • 分布式微服务 - 3.服务网关 - 4.Gateway
    分布式微服务-3.服务网关-4.Gateway项目示例:项目示例-3.服务网关-3.Gateway内容提要:基本使用:配置方式、代码方式内置断言、自定义断言内置局部过滤器、自定义内置和全局过滤器文档:官网官网文档基本使用配置方式引入依赖:使用gateway依赖时,不能同时引入sprin......
  • C# 创建一个分布式文件存储系统需要怎么设计??
    创建一个分布式文件存储系统在C#中涉及的技术栈和架构设计相对复杂,主要包括以下几个关键步骤和技术考量:设计阶段系统架构设计:Tracker服务:设计跟踪服务器(TrackerServer),负责管理存储节点(StorageServer)的状态,提供文件存储位置索引服务。存储节点:设计存储节点,用于实际存储文......
  • 分布式系统:进程间通信
    目录进程间通信概述互联网协议API进程间通信的特征套接字UDP数据报通信TCP流通信外部数据表示和编码外部数据表示常用的表示和编码方法远程对象引用组播通信网络虚拟化和覆盖网络参考资料进程间通信概述进程间通信(interprocesscommunication)主要讨论了分布式系统进程之间......
  • 十分钟掌握分布式数据库开发:OpenMLDB 开发者镜像详解
    OpenMLDB是一款国产的、开源的、面向时序数据的分布式内存数据库系统,它专注于高性能、高可靠性和易扩展性,适用于海量时序数据的处理以及在线特征的实时计算。在大数据和机器学习的浪潮中,OpenMLDB以其强大的数据处理能力和高效的机器学习支持,在开源数据库领域崭露头角。OpenMLDB......
  • 开源.NET8.0小项目伪微服务框架(分布式、EFCore、Redis、RabbitMQ、Mysql等)
    1、前言为什么说是伪微服务框架,常见微服务框架可能还包括服务容错、服务间的通信、服务追踪和监控、服务注册和发现等等,而我这里为了在使用中的更简单,将很多东西进行了简化或者省略了。年前到现在在开发一个新的小项目,刚好项目最初的很多功能是比较通用的,所以就想着将这些功能......
  • 分布式与集群--一起学习吧之架构
    分布式和集群都是为了提高系统的性能和可靠性而采用的技术手段。它们在实际应用中各有优势,可以互相结合使用,以实现更好的系统性能和健壮性。一、区别组织结构:分布式:将一个复杂的业务系统拆分成多个子业务系统,每个子业务系统部署在不同的服务器上。这意味着,不同的子业务运行......