You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4.7 KiB

跟踪日志学习

从设计的角度来讲,跟踪诊断采用观察者模式。 应用程序利用 Source 将希望写入的日主以事件的形式发布出去Listener 作为观察者在接收到日志之后执行一些过滤逻辑,并将活合的日志写入各自的输出渠道,不适合日志的则直接忽略。

每一条日志可以认为是对某一个事件的记录,所以日主大都有一个事件 ID。按照重要程度和反映问题的严重级别我们赋予日志事件一个等级或者类型。 对于以 TaceSource 来说,日志事件等级或者类型通过 TraceEventType 枚举类型事示。除此之外,它还提供了一个 SourceLevels 类型的枚举来完成基于等级的日主事件过滤。

在利用 TraceSource 来记录日志时,我们需要做的就是根据名称和最低日志等级创建一个 TraceSource 对象并将事件ID、事件类型和日志消息作为参数调用它的 TraceEvent 方法。

如下面的代码片段所示,创建一个 TraceSource对象并将名称和最低日志等级分别设置为 Foobar 与 SourceLevels.All后者决定了所有等级的日本都会地记录下来我们针对每种事件类型记录了一条日志消息而事件ID被设置为一个自增的整数


	using System.Diagnostics;

	var source = new TraceSource("TraceLog", SourceLevels.All);
	var eventTypes = (TraceEventType[])Enum.GetValues(typeof(TraceEventType));
	var eventId = 1;

	Array.ForEach(eventTypes, it =>
	{
		source.TraceEvent(it, eventId++, $"这是一个 {eventTypes} 跟踪日志信息");
	});

日志框架大都采用订阅发布模式来记录日志,但是上面的程序只涉及作为发布者的 TraceSource 对象,作为真正完成日志写入的订阅者(监听器)没有出现。 如果以Debug的方式运行程序就会发现相应的日志输出到 Visual Studio 的输出窗口中,这是因为日志框架会默认注册一个类型为 DefaultTraceListener 的监听器,它将日志作为调试信息进行了输出。 TraceEventType 枚举类型共定义了10种事件类型并且对应的枚举项是从高到低排列的Critical 最高Transfer最低所以上面的演示程序会按照等级的高低输出10条日志。 如果只希望部分事件类型的日志被记录下来则应该如何做呢?一般来说,等级越高越应该被记录下来。创建 TraceSource对象时指定的 SourceLevels枚举表示需要被记录下来的最低日志等级。 如果只希望记录Warning等级以上的日志则可以将演示程序进行如下改写。

	using System.Diagnostics;

	var source = new TraceSource("TraceLog", SourceLevels.Warning);
	var eventTypes = (TraceEventType[])Enum.GetValues(typeof(TraceEventType));
	var eventId = 1;

	Array.ForEach(eventTypes, it =>
	{
		source.TraceEvent(it, eventId++, $"这是一个 {eventTypes} 跟踪日志信息");
	});

由于将最低日志等级设置成 SourceLevels.Warning当以Debug模式运行程序后只有等级不低于 WarningWarning、Error和Critical)的3条日志消息写入 Visual Studio 的调试输出窗口。

到目前为止,我们都在使用系统默认注册的 DefaultTraceListener 监听器来完成对日志消息的输出。 DefaultTraceListener 除了调用 Debug 的 Write 方法将指定的消息作为调试信息进行输出,它还支持物理文件的输出方式。 如果需要,则还可以针对期望的输出渠道注册自定义的 TraceListerner.

	public class ConsoleTraceListener : TraceListener
	{

		public override void Write(string? message)
		{
			Console.Write(message);
		}
		public override void WriteLine(string? message)
		{
			Console.WriteLine(message);
		}
	}

在上面的代码片段中,,我们通过继承抽象类 Tacetistener 自定义了一个 ConsoleListener 类型。 它通过重写的 Write 方法和 WriteLine 方法将分发给它的日志输出到控制台上。 这个自定义的ConsoleListener可以通过如下方式来使用。

	using System.Diagnostics;
	var source = new TraceSource("ConsoleTraceLog", SourceLevels.All);
	source.Listeners.Add(new ConsoleListener());
	var eventTypes = (TraceEventType[])Enum.GetValues(typeof(TraceEventType)); 
	var enentId = 1;
	Array.ForEach(eventTypes, it => 
	{
		source.TraceEvent(it, enentId++, $"这是一个 {eventTypes} 跟踪日志信息");
	});

如上面的代码片段所示TraceSource 对象的 Listeners 属性维护了一组注册的 TraceListener 对象。我们只需要将创建的 ConsoleListener 对象添加到这个列表。 由于这个针对控制台的 TraceListener 的存在所以满足过滤条件的3条日志消息输出到控制台上。