65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET 5 使用 Trace Listeners 进行日志记录及如何过滤日志条目

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (2投票s)

2016年1月20日

CPOL

6分钟阅读

viewsIcon

36062

本文介绍了如何在新的 ASP.NET 5 项目中使用跟踪框架,以及 ASP.NET 5 中的日志记录工作方式,同时还介绍了一些在使用跟踪侦听器过程中需要注意的陷阱。此外,还展示了如何使用跟踪侦听器过滤日志消息的方法。

源代码可在 GitHub 获取

 

ASP.NET 5 的可插入式日志记录框架...

ASP.NET 5 是一个全新的开源、跨平台框架,用于使用 .NET 构建现代 Web 应用程序。新框架内置了对日志记录的支持,并允许您与其他日志记录框架集成。您可能需要编写一些代码作为 ASP.NET 日志记录框架与您首选的日志记录提供程序之间的桥梁,方法是实现 ASP.NET 5 提供的接口,例如 ILoggingProviderILogger

 

我们可以插入跟踪侦听器吗……?

在本文中,我将介绍如何在 ASP.NET 5 项目中使用现有的跟踪框架。跟踪功能自 .NET 诞生以来就一直存在。人们已经投入了精力使用跟踪侦听器,它们可以将跟踪消息写入各种目标,例如本地文件、数据库表等。他们应该能够在 ASP.NET 5 项目中也重用他们的投资。让我们来看看如何实现。

 

不再有 web.config...

在 ASP.NET 4.x 中使用跟踪功能非常直接。您可以使用 web.config 文件定义跟踪源并添加跟踪侦听器。例如,如下所示:

<system.diagnostics>
  <trace autoflush="true"></trace>
  <sources>
    <source name="MyServiceTraceSource" switchvalue="All">
      <listeners>
        <add name="MyServiceListener" type="System.Diagnostics.TextWriterTraceListener" initializedata="MyServiceLog.txt"></add>
      </listeners>
    </source>
  </sources>
</system.diagnostics>

然后,在您的代码中,您将消息写入跟踪源,该消息将被配置给该跟踪源的跟踪侦听器接收。这在 ASP.NET 5 中已发生变化,因为它不使用 web.config 文件,我们失去了我们所习惯的配置能力。不过,没有任何东西阻止我们使用新的 JSON 配置文件定义跟踪侦听器配置,然后在代码中使用它来创建侦听特定跟踪源的跟踪侦听器。目前,在这篇文章中,我将直接在代码中使用跟踪侦听器。 

 

 

添加跟踪提供程序...

ASP.NET 5 有自己的日志记录框架,所以我们需要将跟踪侦听器提供程序插入到 ASP.NET 5 日志记录框架中。要在 ASP.NET 5 中使用跟踪侦听器,您需要向项目中添加一个名为 Microsoft.Extensions.Logging.TraceSource 的 NuGet 包。它是由 asp.net 团队开发的,是 aspnet/Logging 项目的一部分。它允许您通过使用 TraceSourceLogger 类在 ASP.NET 5 项目中使用 TraceSourceTraceListener。 

您需要将 Microsoft.Extensions.Logging.TraceSource 包作为依赖项添加到 project.json 文件中,如下所示:

"dependencies": {
    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging.TraceSource": "1.0.0-rc1-final"
},

 

添加跟踪侦听器...

接下来,您需要将一个跟踪源侦听器添加到日志工厂中:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddTraceSource(
        new SourceSwitch("AspNet5LoggingSwitch", "Verbose"),
        new TextWriterTraceListener("AspNet5LoggingService.txt")
    );
    ...
}
    

注意:TextWriterTraceListener 在 .Net Core 中不可用,只在 .Net Framework 中可用。因此,一旦您在代码中使用它,您可能会遇到编译错误。如果出现这种情况,您需要通过修改 project.json 文件从项目中删除 dnxcore50 目标框架,即删除下面高亮显示的行:

    "frameworks": {
      "dnx451": { },
      "dnxcore50": { }
    },

 

获取日志记录器...

最后,您需要通过向类注入对日志记录器实例的依赖项来在类中获取日志记录器实例。有几种选项可用于向类构造函数添加对日志记录器实例的依赖项:

1. 一种选择是将 ILoggerFactory 类型用作依赖项,然后通过在工厂实例上调用 CreateLogger 方法并传入类别名称来手动创建日志记录器。

2. 另一种选择是在构造函数中使用 Logger<T> 作为依赖项,并指定泛型类型参数。

使用 ILoggerFactory 时,您需要手动创建日志记录器,而使用 Logger<T> 时,您可以直接开始使用它进行日志记录。在大多数情况下,使用 Logger<T> 即可满足需求,但当您不知道要使用的泛型类型参数时,或者如果您想创建具有特定类别名称的日志记录器,您可以使用 ILoggerFactory。让我们通过示例来了解这两种方法:

    [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        private readonly ILogger<ValuesController> logger;
        public ValuesController(ILogger<ValuesController> logger)
        {
            this.logger = logger;
        }
        ...
    }

或者

    [Route("api/values2")]
    public class ValuesController2 : Controller
    {
        private readonly ILogger logger;
        public ValuesController2(ILoggerFactory loggerFactory)
        {
            this.logger = loggerFactory.CreateLogger("AspNet5LoggingService");
        }
        ...
    }

 

使用日志记录器...

搞定!您已完成,现在可以开始使用此日志记录器实例来写入日志条目了。

    [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        private readonly ILogger logger;
        public ValuesController(ILogger logger)
        {
            this.logger = logger;
        }
        // GET: api/values
        [HttpGet]
        public IEnumerable Get()
        {
            logger.LogInformation("Processing GET request for values.");
            return new string[] { "value1", "value2" };
        }
    }

执行时,它会在跟踪目标中写入日志条目,在本例中是使用 TextWriterTraceListener 指定的日志文件。

 

冗余的日志条目...

您会发现日志文件在 wwwroot 文件夹中创建,并且包含了所有日志条目。但是,您会注意到,日志文件还包含了 ASP.NET 5 框架生成的所有日志条目。您会看到类似这样的内容:

    
    Microsoft.AspNet.Hosting.Internal.HostingEngine Verbose: 4 : Hosting starting
    Microsoft.AspNet.Hosting.Internal.HostingEngine Verbose: 5 : Hosting started
    Microsoft.AspNet.Hosting.Internal.HostingEngine Information: 1 : Request starting HTTP/1.1 GET https://:50998/api/values
    Microsoft.AspNet.Hosting.Internal.HostingEngine Information: 1 : Request starting HTTP/1.1 DEBUG https://:50998/ text/html
    Microsoft.AspNet.StaticFiles.StaticFileMiddleware Verbose: 1 : DEBUG requests are not supported
    Microsoft.AspNet.StaticFiles.StaticFileMiddleware Verbose: 4 : The request path /api/values does not match a supported file type
    ...
    ...
    AspNet5LoggingService Information: 0 : Processing GET request for values.    

此行为是设计使然。所有日志提供程序都会收到所有日志消息,由各个提供程序自行决定过滤它们感兴趣的消息“类别”。很可能,您不希望在日志文件中看到所有这些条目以及您的服务代码创建的日志条目,这就引出了下一步。

 

如何过滤日志条目……?

您可以通过向 TraceListener 添加过滤器来过滤日志条目,过滤器定义为 TraceListener 基类的一个属性。它的类型为 TraceFilter

public System.Diagnostics.TraceFilter Filter { get; set; }

 

如果您查看 TraceFilter 类的定义,您会发现它是一个抽象类。有一些默认的 TraceFilter 实现可用,您可以使用它们,或者很容易创建自己的过滤器。您所要做的就是派生一个类 TraceFilter 并重写 ShouldTrace 方法。在本例中,我将使用 .NET 自带的现有 SourceFilter 类。

您可以通过以下方式将 TraceFilter 添加到您的侦听器中:

    var listener = new TextWriterTraceListener("AspNet5LoggingService.txt");
    listener.Filter = new SourceFilter("AspNet5LoggingService");
    loggerFactory.AddTraceSource(
        new SourceSwitch("AspNet5LoggingSwitch", "Verbose"),
        listener
    );

 

我的过滤后的日志条目在哪里……?

根据您的项目以及生成的日志条目数量,可能会出现您在日志文件中看不到任何新的跟踪消息的情况,尤其是在过滤了由您的服务代码生成的跟踪消息之后。如果您使用的是 TextWriterTraceListener,您可能不会立即在日志文件中看到您的日志条目,尽管日志文件会立即创建(如果它尚不存在)。这就是我遇到的困难,花了相当长的时间调试为什么我的文件中看不到日志条目,后来才了解到我所使用的特定侦听器的一个功能。这是因为 TextWriterTraceListener 将数据写入文件流,并且这些跟踪消息被缓冲。它不会在每次写入时刷新缓冲的数据。在 .NET 的早期版本中,您通常会在 web.config 文件中添加以下内容:

<trace autoflush="true" />

 

这将导致跟踪侦听器立即刷新跟踪消息。要在 ASP.NET 5 中实现相同的功能,您可以在代码中添加以下内容:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        // This would prevent TextWriterTraceListener from buffering trace messages but cause
        // it to flush them as each trace message is sent to listener
        if (env.IsDevelopment())
        {
            Trace.AutoFlush = true;
        }        

        var listener = new TextWriterTraceListener("AspNet5LoggingService.txt");
        listener.Filter = new SourceFilter("AspNet5LoggingService");
        loggerFactory.AddTraceSource(
            new SourceSwitch("AspNet5LoggingSwitch", "Verbose"),
            listener
        );
        ...
    }

我选择 AutoFlush 行为仅在开发环境中使用,因为那是我们需要日志条目立即反映在文件中的地方,而在生产环境中,缓冲日志消息可以提供更好的性能。如果您不设置 AutoFlush 属性,您将需要等待直到流中的缓冲数据被写入到磁盘文件。

 

总结...

在本文中,我们了解了如何:

1. 在 ASP.NET 5 项目中使用跟踪侦听器

2. 在跟踪侦听器级别过滤跟踪条目

3. 在代码中使用 Trace.AutoFlush 来防止跟踪消息在内存中被缓冲

 

注意:请注意,本文使用 ASP.NET 5 RC1 编写,到 RTM 发布(预计在接下来的几个月内)时,可能会有一些更改。

 

编码愉快。

Vande Mataram!

(向祖国致敬)

 

© . All rights reserved.