.NET Core的日志[5]:利用TraceSource写日志
从微软推出第一个版本的.NET Framework的时候,就在“System.Diagnostics”命名空间中提供了Debug和Trace两个类帮助我们完成针对调试和跟踪信息的日志记录。在.NET Framework 2.0中,微软引入了TraceSource并对跟踪日志系统进行了优化,优化后的跟踪日志系统在.NET Core中又经过了相应的简化。.NET Core的日志模型借助TraceSourceLoggerProvider实现对TraceSource的整合,在正式介绍这个Logger之前,我们先来认识一下TraceSource跟踪日志系统中的三个核心对象。[ 本文已经同步到《ASP.NET Core框架揭秘》之中]
一、基于TraceSource的追踪日志系统对于这个基于TraceSource的跟踪日志系统来说,除了TraceSource之外,它还具有额外连个核心的对象,它们分别是TraceListener和SourceSwitch,三者之间的关系如下图所示。日志消息的写入实现在TraceListener上,我们可以将一组TraceListener注册到某个TraceSource之上。当我们利用TraceSource记录某条跟踪日志时,日志消息会分发给注册的每一个TraceListener并由它们将日志消息写到对应的目的地。每个TraceSource都具有一个SourceSwitch,后者起到了日志过滤的作用。具体来说,SourceSwitch定义了相应的过滤条件来帮助TraceSource决定是否应该将跟踪日志分发给TraceListener,如果指定的日志消息不满足过滤条件,TraceSource将不会进行任何实质性的日志记录工作。 如下所示的是TraceSource的定义。每一个TraceSource都具有一个名称,它一般代表写入跟踪日志的应用程序、服务或者组件的名称。我们可以调用它的三组Trace方法(TraceData、TraceEvent和TraceInformation)来记录跟踪日志。由于这些方法都标注了一个ConditionaleAttribute特性并将条件编译符“TRACE”,所以针对这些方法的调用只有在针对Trace模式编译的应用中才是有效的。 1: public class TraceSource 2: {
3: public TraceListenerCollection Listeners { get; } 4: string Name { get; } 5: public SourceSwitch Switch { get; set; } 6:?
7: public TraceSource(string name); 8: string name,SourceLevels defaultLevel); 9:
10: [Conditional("TRACE")] 11: void TraceData(TraceEventType eventType,int id,1)">object data); 12: [Conditional( 13: params object[] data); 14:?
15: [Conditional( 16: void TraceEvent(TraceEventType eventType,1)">int id); 17: [Conditional( 18: string message); 19: [Conditional( 20: string format,1)">object[] args); 21:?
22: [Conditional( 23: void TraceInformation( 24: [Conditional( 25: object[] args); 26: }
通过TraceData、TraceEvent和TraceInformation这三个方法记录的跟踪日志都具有一个通过枚举类型TraceEventType表示的事件类型,它相当于前面提到的日志等级。TraceEventType的这些枚举项的值越小意味着等级越高,定义日志等级的LogLevel则于此相反。在调用TraceData和TraceEvent方法时,我们需要显式地为写入的跟踪日志指定事件类型,而TraceInformation方法则默认使用Information类型。 3: Critical = 1,
1: [Flags] 3: { 9: Information = 15,1)"> 10: Verbose = 31 class SourceSwitch : Switch 4:? 7:? 9: { 11: } abstract class TraceListener : IDisposable
virtual void TraceData(TraceEventCache eventCache,1)">string source,TraceEventType eventType,1)">void TraceEvent(TraceEventCache eventCache,1)"> 9: 10: } 接下来我们通过一个简单的控制台应用来演示如何创建一个TraceSource并使用它来记录追踪日志。由于TraceSource定义在“System.Diagnostics.TraceSource”这个NuGet包中,我们需要在project.json文件中需要按照如下的方式添加针对这个NuGet包的依赖。和前面演示的实例一样,为了提供针对中文编码的支持,我们不得不添加针对“System.Text.Encoding.CodePages”这个NuGet包的依赖。 2: ...
"System.Diagnostics.TraceSource": "4.0.0",1)">"System.Text.Encoding.CodePages": "4.0.1" 7: } 由于TraceSource总是利用注册在它上面的TraceListener来完成写日志的工作,所以我们按照如下的方式自定义了ConsoleTraceListener。顾名思义,ConsoleTraceListener旨在将分发给它的追踪日志输出到控制台上。如下面的代码片段所示,这个ConsoleTraceListener仅仅重写了Write和WriteLine方法,它们调用定义在Console类型上的同名方法将格式化好的日志消息输出到控制台上。 override void Write(string message) => Console.Write(message);
5: } 我们在作为程序入口的Main方法中创建了一个TraceSource对象。在调用构造函数的时候,除了指定TraceSource的名称(“Program”)之外,我们还设置了一个默认的追踪日志等级(Warning)。接下来我们创建了一个ConsoleTraceListener对象并将其注册到TraceSource对象上。在此之后,我们调用TraceSource的TraceEvent方法记录了三条追踪日志,它们采用的追踪事件类型分别是Information、Warining和Error。 static void Main(string[] args)
5: //注册EncodingProvider实现对中文编码的支持
8: TraceSource traceSource = new TraceSource(nameof(Program),SourceLevels.Warning);
10:? 12: traceSource.TraceEvent(TraceEventType.Information,eventId,1)">"升级到最新.NET Core版本({0})",1)">"1.0.0"); 14: traceSource.TraceEvent(TraceEventType.Error,1)">"数据库连接失败(数据库:{0},用户名:{1})",1)">"TestDb",1)">"sa"); 16: } 该程序运行之后,我们利用TraceSource记录的追踪日志将会被注册的ConsoleTraceListener按照如下图所示的形式输出到控制台上。由于我们在创建TraceSource的时候指定了一个默认的追踪日志等级Warning,所以只有不低于这个等级的两条日志才会显示在控制台上。 二、TraceSourceLogger.NET Core的日志模型利用一个定义在NuGet包“Microsoft.Extensions.Logging.TraceSource”中的TraceSourceLogger类型实现与TraceSource跟踪日志系统的整合。从如下面的代码片段我们不难看出,一个TraceSourceLogger对象实际上就是对一个TraceSource对象的封装,在实现的Log<State>方法中,它会调用TraceSource的TraceEvent方法来完成针对日志消息的写入工作。 public TraceSourceLogger(TraceSource traceSource);
bool IsEnabled(LogLevel logLevel); 7: } 当我们调用TraceSource的TraceEvent方法来写追踪日志的时候,需要指定追踪日志的事件类型,该类型由提供的日志等级来决定,下表展示了日志等级与跟踪事件类型之间的映射关系很简单。 由于TraceSource通过调用其SourceSwitch的ShouldTrace方法来决定是否真正需要写入当前分发的追踪日志消息,所以当TraceSourceLogger的IsEnabled方法被调用的时候,它也会按照这样的映射关系将指定的日志等级转换成追踪事件类型,并将其作为参数调用这个ShouldTrace方法,这个方法的返回值就是IsEnabled方法的返回值。
TraceSourceLogger的BeginScope<TState>方法会返回一个TraceSourceScope对象,虽然这是一个共有的类型,但是这个对象并不做任何作用域的控制,其自身也不携带任何关于当前日志上下文的信息,所以TraceSourceLogger和前面介绍的DebugLogger和EventLogLogger一样,其实都不提供针对日志上下文的支持。 三、TraceSourceLoggerProviderTraceSourceLogger对应的LoggerProvider类型为TraceSourceLoggerProvider。如下面的代码片段所示,当我们创建一个TraceSourceLoggerProvider对象时需要提供一个SourceSwitch和TraceListener对象(可选)。在实现的CreateLogger方法中,TraceSourceLoggerProvider会根据指定的名称创建一个TraceSource对象,它将采用初始化时指定的SourceSwitch,预先指定的TraceListener也会注册到这个TraceSource对象上,CreateLogger方法最终返回的将是根据这个TraceSource创建的TraceSourceLogger。 2: {
public TraceSourceLoggerProvider(SourceSwitch rootSourceSwitch,TraceListener rootTraceListener); public ILogger CreateLogger(void Dispose();
class TraceSourceFactoryExtensions string switchName,1)"> 5: } 接下来我们通过一个简单的实例来演示针对DebugLogger的日志记录。我们创建一个空的控制台应用,在添加必要的依赖之后,我们在Main方法中编写了如下一段程序。如下面的代码片段所示,我们采用依赖注入的方式创建了一个LoggerFactory,并调用扩展方法AddTraceSource方法创建并注册了一个TraceSourceLoggerProvider对象。在利用LoggerFactory创建出Logger对象之后,我们利用后者记录了三条日志消息。 9: .AddLogging()
11: .GetService<ILoggerFactory>() 13: .CreateLogger<Program>(); 16: 17:?
22: } 我们在调用扩展方法AddTraceSource创建并注册TraceSourceLoggerProvider是指定了一个针对Warning等级的SourceSwitch,而指定的TraceListener是一个自定义的ConsoleTraceListener,所以只有两条等级不低于Warning的日志消息会被这个ConsoleTraceListener按照上图所示的形式输出到控制台上。 .NET Core的日志[1]:采用统一的模式记录日志 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-mvc – ASP.net MVC – FluentValidation单元测试
- ASP.NET / VB.NET:Dropdownlist SelectedIndexChanged没有
- asp.net-mvc – 用于对Office 365 AD进行身份验证的MVC
- asp.net – 无法CoCreate Profiler错误 – 但不使用分析器
- asp.net – 无论如何要在上传之前确定文件大小?
- asp.net-mvc – 如何获取某些代码在ASP.NET MVC 2中的每个单
- asp.net-mvc – 在mvc 5和web api 2之间共享owin cookie身份
- asp.net – 链接到页面上的不同区域
- asp.net-mvc – ASP.NET MVC与Zeitgeist
- asp.net-mvc – ASP.NET MVC SiteMap提供程序-Razor