Asp.Net Core轻松学之利用日志监视进行服务遥测详

在 Net Core 2.2 中,官方文档表示,对 EventListener 这个日志监视类的内容进行了扩充,同时赋予了跟踪 CoreCLR 事件的权限;通过跟踪 CoreCLR 事件,比如通过跟踪 CoreCLR 事件,可以了解和收集到比如 GC,JIT,ThreadPool,intreop 这些运行时服务的行为;通过使用配置注入,我们将获得一种动态跟踪事件的能力。

1. EventListener 介绍

1.1 EventListener 中文直译为:事件侦听器

EventListener 位于程序集 System.Diagnostics.Tracing 中,该类提供了一组启用/禁用的方法,按照惯例,先来看一下源代码,了解一下其结构

public abstract class EventListener : IDisposable { protected EventListener(); public event EventHandler<EventSourceCreatedEventArgs> EventSourceCreated; public event EventHandler<EventWrittenEventArgs> EventWritten; protected static int EventSourceIndex(EventSource eventSource); public void DisableEvents(EventSource eventSource); public virtual void Dispose(); public void EnableEvents(EventSource eventSource, EventLevel level); public void EnableEvents(EventSource eventSource, EventLevel level, EventKeywords matchAnyKeyword); protected internal virtual void OnEventWritten(EventWrittenEventArgs eventData); }

从类结构中可以看出,EventListener 中的方法并不多,而且从名字都可以推断出其行为,
因为该类是一个抽象类,并不能直接使用,接下来我们创建一个 ReportListener 类继承它

2. 创建自定义事件侦听器

public class ReportListener : EventListener { public ReportListener() { } public Dictionary<string, ListenerItem> Items { get; set; } = new Dictionary<string, ListenerItem>(); public ReportListener(Dictionary<string, ListenerItem> items) { this.Items = items; } protected override void OnEventSourceCreated(EventSource eventSource) { if (Items.ContainsKey(eventSource.Name)) { var item = Items[eventSource.Name]; EnableEvents(eventSource, item.Level, item.Keywords); } } protected override void OnEventWritten(EventWrittenEventArgs eventData) { if (Items.ContainsKey(eventData.EventSource.Name)) { Console.WriteLine($"ThreadID = {eventData.OSThreadId} ID = {eventData.EventId} Name = {eventData.EventSource.Name}.{eventData.EventName}"); for (int i = 0; i < eventData.Payload.Count; i++) { string payloadString = eventData.Payload[i]?.ToString() ?? string.Empty; Console.WriteLine($"\tName = \"{eventData.PayloadNames[i]}\" Value = \"{payloadString}\""); } Console.WriteLine("\n"); } } }

ReportListener 自定义事件侦听器的代码非常简单,只是简单的继承了 EventListener 后,重写了父类的两个方法:创建事件和写入事件

同时,还定义了一个公共属性 Dictionary<string, ListenerItem> Items ,该属性接受一个 ListenerItem 的跟踪配置集,通过配置文件注入,动态觉得哪些事件可以被写入到侦听器中

3. 配置跟踪项目

在配置文件 appsettings.json 中增加以下内容

{ "listener": [ { "name": "HomeEventSource", "level": 5, "keywords": -1 } ] }

配置说明

上面的配置文件表示,定义一个事件源对象(EventSource),名称为 HomeEventSource,事件级别(EventLevel)为 5,关键字(EventKeywords)为 -1

关于事件级别和事件关键字的值,和系统定义的一致

3.1 事件级别定义

namespace System.Diagnostics.Tracing { public enum EventLevel { LogAlways = 0, Critical = 1, Error = 2, Warning = 3, Informational = 4, Verbose = 5 } }

3.2 事件关键字定义

namespace System.Diagnostics.Tracing { [Flags] public enum EventKeywords : long { All = -1, None = 0, WdiContext = 562949953421312, MicrosoftTelemetry = 562949953421312, WdiDiagnostic = 1125899906842624, Sqm = 2251799813685248, AuditFailure = 4503599627370496, CorrelationHint = 4503599627370496, AuditSuccess = 9007199254740992, EventLogClassic = 36028797018963968 } }

3.3 配置文件完全按照系统值定义,为了更好的使用配置文件,我们定义了下面的实体类

public class ListenerItem { public string Name { get; set; } public EventLevel Level { get; set; } = EventLevel.Verbose; public EventKeywords Keywords { get; set; } = EventKeywords.All; }

4. 开始使用事件侦听器

为了在应用程序中使用事件侦听器,我们需要初始化事件侦听器,你可以初始化多个事件侦听器;但是,每个事件侦听器仅需要初始化一次即可

4.1 初始化自定义事件侦听器,在 Startup.cs 文件中加入以下代码

public void AddEventListener(IServiceCollection services) { var listeners = this.Configuration.GetSection("listener").Get<List<ListenerItem>>(); Dictionary<string, ListenerItem> dict = new Dictionary<string, ListenerItem>(); if (listeners != null) { foreach (var item in listeners) { dict.Add(item.Name, item); } } var report = new ReportListener(dict); services.AddSingleton<ReportListener>(report); } public void ConfigureServices(IServiceCollection services) { AddEventListener(services); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }

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

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