diff --git a/LogStudy.TraceLog/CustomTraceListener.cs b/LogStudy.TraceLog/CustomTraceListener.cs new file mode 100644 index 0000000..c98b14e --- /dev/null +++ b/LogStudy.TraceLog/CustomTraceListener.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LogStudy.TraceLog +{ + public class CustomTraceListener : TraceListener + { + public override void Write(string? message) + { + Console.Write(message); + } + + public override void WriteLine(string? message) + { + Console.WriteLine(message); + } + } +} diff --git a/LogStudy.TraceLog/Program.cs b/LogStudy.TraceLog/Program.cs index 1bc52a6..040e011 100644 --- a/LogStudy.TraceLog/Program.cs +++ b/LogStudy.TraceLog/Program.cs @@ -1 +1,41 @@ -Console.WriteLine("Hello, World!"); +using System.Diagnostics; +using LogStudy.TraceLog; + +Console.WriteLine("======== 跟踪日志学习 ========"); + +//UseDefaultListener(); + +UseCustomListener(); + +//使用默认监听器 +void UseDefaultListener() +{ + 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} 跟踪日志信息"); + }); +} + +//使用自定义监听器 +void UseCustomListener() +{ + var source = new TraceSource("ConsoleListenerTraceLog", SourceLevels.All); + source.Listeners.Clear(); + source.Listeners.Add(new DefaultTraceListener() { LogFileName="DefaultListenerTrace.log"}); + source.Listeners.Add(new CustomTraceListener() { IndentSize=8,IndentLevel=3}) ; + + var eventTypes = (TraceEventType[])Enum.GetValues(typeof(TraceEventType)); + var eventId = 1; + + Array.ForEach(eventTypes, it => + { + source.TraceEvent(it, eventId++, $"这是一个 {it} 跟踪日志信息"); + }); +} + + + diff --git a/LogStudy.TraceLog/study.md b/LogStudy.TraceLog/study.md new file mode 100644 index 0000000..5218465 --- /dev/null +++ b/LogStudy.TraceLog/study.md @@ -0,0 +1,85 @@ +# 跟踪日志学习 +从设计的角度来讲,跟踪诊断采用观察者模式。 +应用程序利用 Source 将希望写入的日主以事件的形式发布出去,Listener 作为观察者在接收到日志之后执行一些过滤逻辑,并将活合的日志写入各自的输出渠道,不适合日志的则直接忽略。 + + +每一条日志可以认为是对某一个事件的记录,所以日主大都有一个事件 ID。按照重要程度和反映问题的严重级别,我们赋予日志事件一个等级或者类型。 +对于以 TaceSource 来说,日志事件等级或者类型通过 TraceEventType 枚举类型事示。除此之外,它还提供了一个 SourceLevels 类型的枚举来完成基于等级的日主事件过滤。 + +在利用 TraceSource 来记录日志时,我们需要做的就是根据名称和最低日志等级创建一个 TraceSource 对象,并将事件ID、事件类型和日志消息作为参数调用它的 TraceEvent 方法。 + +如下面的代码片段所示,创建一个 TraceSource对象,并将名称和最低日志等级分别设置为 Foobar 与 SourceLevels.All,后者决定了所有等级的日本都会地记录下来,我们针对每种事件类型记录了一条日志消息,而事件ID被设置为一个自增的整数 +```csharp + + 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等级以上的日志,则可以将演示程序进行如下改写。 + +```csharp + 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模式运行程序后,只有等级不低于 Warning(Warning、Error和Critical)的3条日志消息写入 Visual Studio 的调试输出窗口。 + +到目前为止,我们都在使用系统默认注册的 DefaultTraceListener 监听器来完成对日志消息的输出。 +DefaultTraceListener 除了调用 Debug 的 Write 方法将指定的消息作为调试信息进行输出,它还支持物理文件的输出方式。 +如果需要,则还可以针对期望的输出渠道注册自定义的 TraceListerner. + +```csharp + 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可以通过如下方式来使用。 + +```csharp + 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条日志消息输出到控制台上。 diff --git a/LogStudy.sln b/LogStudy.sln index e3b5919..0c01e79 100644 --- a/LogStudy.sln +++ b/LogStudy.sln @@ -6,6 +6,9 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogStudy.WebApp", "LogStudy.WebApp\LogStudy.WebApp.csproj", "{8516CD13-0513-46AF-897F-05FCD66933A2}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DebugLog", "DebugLog", "{2319453B-2895-48E4-99A3-123ADED51280}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TraceLog", "TraceLog", "{353B9475-1064-473D-B3EE-CF3A9BBA4102}" EndProject @@ -13,13 +16,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EventLog", "EventLog", "{78 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DiagnosticLog", "DiagnosticLog", "{D91AB187-F922-47DE-87ED-D3785F4E8D7B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogStudy.DebugLog", "LogStudy.DebugLog\LogStudy.DebugLog.csproj", "{A4CF5770-2855-44C7-B9DA-27332670D03D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogStudy.DebugLog", "LogStudy.DebugLog\LogStudy.DebugLog.csproj", "{A4CF5770-2855-44C7-B9DA-27332670D03D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogStudy.TraceLog", "LogStudy.TraceLog\LogStudy.TraceLog.csproj", "{3D1FA013-7BAC-4D62-B35B-8B444DB7FE8C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogStudy.TraceLog", "LogStudy.TraceLog\LogStudy.TraceLog.csproj", "{3D1FA013-7BAC-4D62-B35B-8B444DB7FE8C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogStudy.EventLog", "LogStudy.EventLog\LogStudy.EventLog.csproj", "{372EA389-4C91-4B05-8270-86788D48F45D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogStudy.EventLog", "LogStudy.EventLog\LogStudy.EventLog.csproj", "{372EA389-4C91-4B05-8270-86788D48F45D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogStudy.DiagnosticLog", "LogStudy.DiagnosticLog\LogStudy.DiagnosticLog.csproj", "{73AC3F84-DC11-4F53-A729-0EA09E124E6E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogStudy.DiagnosticLog", "LogStudy.DiagnosticLog\LogStudy.DiagnosticLog.csproj", "{73AC3F84-DC11-4F53-A729-0EA09E124E6E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/PerfView/PerfView.exe b/PerfView/PerfView.exe new file mode 100644 index 0000000..eb6ec85 Binary files /dev/null and b/PerfView/PerfView.exe differ