在 .NET Core 中使用 Diagnostics (Diagnostic Source) 记录跟踪信息 (2)

如何生成 Diagnostic 日志记录呢?首先,我们需要创建一个 DiagnosticListener 对象,比如:

private static DiagnosticSource httpLogger = new DiagnosticListener("System.Net.Http");

DiagnosticListener 参数中的名称即为需要监听的事件(组件)名称,这个名称在以后会被用来被它的消费者所订阅使用。

DiagnosticSource 其核心只包含了两个方法,分别是 :

bool IsEnabled(string name) void Write(string name, object value);

那么然后我们可以这样来调用:

if (httpLogger.IsEnabled("RequestStart")){ httpLogger.Write("RequestStart", new { Url="http://clr", Request=aRequest }); }

IsEnabled(string param1) 这个方法用来判断是否有消费者注册了当前的事件(组件)名称监听,通常有消费者关心了相关数据,我们才会进行事件记录。
Write(string param1,object param2) 这个方法用来向 DiagnosticSource 中写入日志记录,param1 和上面一样用来指定名称的,也就是所向指定名称中写入数据,param2 即为写入的 payloads 数据,你可以使用 匿名类型来向 param2 中写入数据,这样会方便很多。

这样,我们就已经把 Diagnostic 事件日志写入到 DiagnosticSource中了,是不是很简单? 我们再看一下如何进行消费(监听)这些事件信息。

监听 Diagnostic 日志记录

在监听 Diagnostic 日志记录之前你需要知道你要关心的事件数据名称,那么如果仅仅是在代码中把 DiagnosticListeners 都写死到监听的消费者代码中的话,这样就太不灵活了,所以这里设计了一个机制用来发现中那些在运行时被激活的DiagnosticListeners。

你可以使用 DiagnosticListener.AllListeners 来获取一个 IObservable<DiagnosticListener>对象,IObservable接口大家应该都不陌生了吧(不太清楚的可以看这里),然后通过其Subscribe方法进行OnNext“回调”关心的事件数据。

示例代码:

static IDisposable networkSubscription = null; // 使用 AllListeners 来获取所有的DiagnosticListeners对象,传入一个IObserver<DiagnosticListener> 回调 static IDisposable listenerSubscription = DiagnosticListener.AllListeners.Subscribe(delegate (DiagnosticListener listener) { // 当 DiagnosticsListener 激活的时候,这里将获得一个回调用 if (listener.Name == "System.Net.Http") { // 订阅者监听消费代码 lock(allListeners) { if (networkSubscription != null) networkSubscription.Dispose(); //回调业务代码 Action<KeyValuePair<string, object>> callback = (KeyValuePair<string, object> evnt) => Console.WriteLine("From Listener {0} Received Event {1} with payload {2}", networkListener.Name, evnt.Key, evnt.Value); //创建一个匿名Observer对象 Observer<KeyValuePair<string, object>> observer = new AnonymousObserver<KeyValuePair<string, object>>(callback); //筛选你感兴趣的事件 Predicate<string> predicate = (string eventName) => eventName == "RequestStart"; networkSubscription = listener.Subscribe(observer, predicate); } } }); // 通常情况下,这里你需要保持 listenerSubscription 始终处于激活状态, // 如果你像取消回调,你可以调用 listenerSubscription.Dispose() 来取消订阅者

通过这种方式,我们就可以在触发回调的之后做一些我们想要的操作了。

是不是发现上面的那种写法有点麻烦和丑陋,ASP.NET 团队考虑到了,所以为我们封装了一个适配器的库来方便我们进行监听的一些操作,你可以通过打 attribute 标记的方式来进行相关事件的订阅,有兴趣的同学可以看下这个(Microsoft.Extensions.DiagnosticAdapte) NuGet 包。

现在我们已经可以拿到数据了,有同学可能会说在生产环境数据这么多,这些数据我存到哪里,又怎么样来处理呢,我不可能一条一条的来找性能在哪里吧,OK,我们接着往下看。

为你的框架支持 Diagnostics

随着微服务的流行,服务的链路追踪以及应用程序的性能问题变得越来越重要,而 APM 也成为了整个微服务架构中很重要的一个中间件,它可以协助我们快速查找生产环境中所遇到的问题,以及在应用程序发生异常的时候收集异常运行时的上下文信息来快速排查问题。

对 Google 的 Dapper 或者 OpenTracing 协议有了解的同学应该已经想到了,我们可以利用上面的那些数据按照这些协议的约定进行包装,然后发送到支持这些协议的 APM 的服务端,剩下的工作是不是可以由这些服务端来帮助我们处理了,包括图形化展示,性能查看,调用链查看等。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwjsws.html