DiagnosticSource DiagnosticListener 无侵入式分布式跟踪

种地  金牌会员 | 2024-5-14 02:26:05 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 923|帖子 923|积分 2769

ASP.NET Core 中的框架中发出大量诊断变乱,包罗当前请求进入请求完成变乱,HttpClient发出收到与响应,EFCore查询等等。
我们可以利用DiagnosticListener来选择性地监听这些变乱,然后通过自己的方式构造这些日志,实现无侵入的分布式跟踪。
下面我们通过DiagnosticSource监听EFCore,与HTTPClient,实现链路追踪。
创建监听
现在我们将配置一个DiagnosticListener来监听全部变乱。 
首先,我们需要一个IObserver,我们将使用它来订阅全部变乱。
  1. public class TestDiagnosticObserver : IObserver<DiagnosticListener>
  2. {
  3.     public void OnNext(DiagnosticListener value)
  4.     {
  5.         value.Subscribe(new TestKeyValueObserver());
  6.     }
  7.     public void OnCompleted() { }
  8.     public void OnError(Exception error) { }
  9. }
复制代码
 此中重要的方法是OnNext。然后我们传入另一个自定义类型TestKeyValueObserver,这是实际接收实例发出的变乱的类DiagnosticListener。该变乱会接受KeyValuePair参数,我们后续可针对此参数做业务相关的筛选。
  1. public class TestKeyValueObserver : IObserver<KeyValuePair<string, object?>>
  2. {
  3.     public void OnNext(KeyValuePair<string, object?> value)
  4.     {
  5.         var activity = Activity.Current;
  6.         Console.WriteLine($"traceId {activity?.TraceId} Received event: {value.Key}");
  7.     }
  8.     public void OnCompleted() { }
  9.     public void OnError(Exception error) { }
  10. }
复制代码
 
最后一步是在应用步伐中注册我们的步伐TestDiagnosticObserver。
  1. DiagnosticListener.AllListeners.Subscribe(new TestDiagnosticObserver());
复制代码
 
创建HTTP请求与EFCore查询
我们新建一个接口,用来集成EF与HttpClient。并调用这个接口检察DiagnosticListener 监听到的内容
  1. [HttpGet]
  2. public async Task<string> GetAsync()
  3. {
  4.     //HTTP
  5.     await _httpClient.GetAsync("https://www.baidu.com");
  6.     //EF
  7.     Item item = new Item()
  8.     {
  9.         Barcode = Guid.NewGuid().ToString(),
  10.         Brand = "Milky Way",
  11.         Name = "Milk",
  12.         PruchasePrice = 20.5,
  13.         SellingPrice = 25.5
  14.     };
  15.     _productsContext.Items.Add(item);
  16.     _productsContext.SaveChanges();
  17.     return "OK";
  18. }
复制代码
 
调用此接口来看看我们的DiagnosticListener的效果。
可以看到收到了很多Event,包罗当前请求的各个阶段,HttpClient的各个阶段,与EFCore查询的各个阶段。

 
剖析Event
然后修改TestKeyValueObserver,我们从中挑选我们需要的HTTPClient与EFCore相关的变乱。
  1. public class TestKeyValueObserver : IObserver<KeyValuePair<string, object?>>
  2. {
  3.     public void OnNext(KeyValuePair<string, object?> value)
  4.     {
  5.         var activity = Activity.Current;
  6.         //Console.WriteLine($"traceId {activity?.TraceId} Received event: {value.Key}");
  7.         if (value.Key.StartsWith("System.Net.Http.Request"))
  8.         {
  9.             var cEventStr = JsonConvert.SerializeObject(value.Value);
  10.             var cEvent = JsonConvert.DeserializeAnonymousType(cEventStr, new { Request = new { RequestUri = ""} , Timestamp = 2879029490722 });
  11.             Console.WriteLine($"traceId {activity?.TraceId} Request.Start: {cEvent.Timestamp} ");
  12.             Console.WriteLine($"traceId {activity?.TraceId} Request.Uri: {cEvent.Request.RequestUri} ");
  13.         }
  14.         if (value.Key.StartsWith("System.Net.Http.Response"))
  15.         {
  16.             var cEventStr = JsonConvert.SerializeObject(value.Value);
  17.             var cEvent = JsonConvert.DeserializeAnonymousType(cEventStr, new { Request = new { RequestUri = "" }, Timestamp = 2879029490722 });
  18.             Console.WriteLine($"traceId {activity?.TraceId} Http.Response: {cEvent.Timestamp} ");
  19.         }
  20.         if (value.Key.StartsWith("Microsoft.EntityFrameworkCore.Database.Connection.ConnectionOpening"))
  21.         {
  22.             var cEvent = (Microsoft.EntityFrameworkCore.Diagnostics.ConnectionEventData)value.Value;
  23.             Console.WriteLine($"traceId {activity?.TraceId} Connection.ConnectionOpening: {cEvent?.StartTime.ToString("yyyy-MM-dd HH:mm:ss:fff")} ");
  24.         }
  25.         if (value.Key.StartsWith("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting"))
  26.         {
  27.             var cEvent = (Microsoft.EntityFrameworkCore.Diagnostics.CommandEventData)value.Value;
  28.             Console.WriteLine($"traceId {activity?.TraceId}  {cEvent?.Command.CommandText} ");
  29.         }
  30.         if (value.Key.StartsWith("Microsoft.EntityFrameworkCore.Database.Connection.ConnectionClosed"))
  31.         {
  32.             var cEvent = (Microsoft.EntityFrameworkCore.Diagnostics.ConnectionEventData)value.Value;
  33.             Console.WriteLine($"traceId {activity?.TraceId} Connection.ConnectionClosed: {cEvent?.StartTime.ToString("yyyy-MM-dd HH:mm:ss:fff")} ");
  34.         }
  35.     }
  36.     public void OnCompleted() { }
  37.     public void OnError(Exception error) { }
  38. }
复制代码
 
再次启动,检察效果,可以看到已经获取到了http请求的开始竣事变乱,EF的查询语句,开始变乱等。

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

种地

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表