如何降低aspnetcore中mvc管道的日志级别?

时间:2017-08-23 00:49:35

标签: c# asp.net-core asp.net-core-mvc serilog

因此,在ASPNETCORE 2.0项目中,我向日志工厂添加了一个日志记录提供程序(serilog)以及一个控制台接收器。它工作得很好,但我注意到所有框架请求管道(如http请求响应)都将每个小细节记录为INFO。

[17:37:26 INF] Request starting HTTP/1.1 GET http://localhost:5000/test/health
[17:37:26 INF] Executing action method DAS.Gateways.Command.Api.Controllers.TestController.HealthCheck (DAS.Gateways.Command.Api) with arguments (null) - ModelState is Valid
[17:37:26 INF] Health check called.
[17:37:27 INF] Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
[17:37:27 INF] Executed action DAS.Gateways.Command.Api.Controllers.TestController.HealthCheck (DAS.Gateways.Command.Api) in 203.8825ms
[17:37:27 INF] Request finished in 343.9801ms 200 application/json; charset=utf-8
[17:38:07 INF] Request starting HTTP/1.1 GET http://localhost:5000/test/health
[17:38:07 INF] Executing action method DAS.Gateways.Command.Api.Controllers.TestController.HealthCheck (DAS.Gateways.Command.Api) with arguments (null) - ModelState is Valid
[17:38:07 INF] Health check called.
[17:38:07 INF] Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
[17:38:07 INF] Executed action DAS.Gateways.Command.Api.Controllers.TestController.HealthCheck (DAS.Gateways.Command.Api) in 53.5876ms
[17:38:07 INF] Request finished in 60.2195ms 200 application/json; charset=utf-8

Info是我们用于生产日志记录的最小日志级别,我们有一个Loggly接收器,其限制为1GB /天所以我觉得MVC记录了所有请求信息,因为INFO有点令人讨厌,我想降低它去调查。为了清楚起见,我不想提高我的日志记录级别以防止INFO到达接收器,我希望.Net将其日志级别从INFO降低到DEBUG。

这可能吗?如何?

3 个答案:

答案 0 :(得分:6)

您需要使用log filtering

  

您可以为特定提供商和类别或所有提供商或所有类别指定最低日志级别。低于最低级别的任何日志都不会传递给该提供商,因此不会显示或存储它们。

过滤规则可以通过配置或代码定义。它在代码中的外观示例:

    // using Serilog.Extensions.Logging;

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureLogging(logging => 
            {
                logging.AddFilter<SerilogLoggerProvider>("Microsoft", LogLevel.Warning);
            }
            .UseStartup<Startup>()
            .Build();

注意,在这种情况下,AddFilter仅适用于Serilog日志提供程序,因为我们指定了提供程序类型。如果要为所有提供程序定义筛选器,请使用:

logging.AddFilter("Microsoft", LogLevel.Warning);

答案 1 :(得分:1)

一种可能的解决方案是创建自己的ILoggerProviderILogger实现,作为底层提供程序的垫片,然后让您的ILogger.Log()方法根据记录器的类别名称,然后修改日志级别。

就我而言,我假设所有ASP.NET Core应用程序都有以&#34; Microsoft.AspNetCore&#34; 开头的记录器类别名称,然后我将日志级别从Information更改为调试这些事件,例如:

public class MyLogger : ILogger
{
    private string  categoryName;
    private ILogger baseLogger;

    public MyLogger(string categoryName, ILogger baseLogger)
    {
        this.categoryName = categoryName;
        this.baseLogger   = baseLogger;
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        if (logLevel == LogLevel.Information 
           && categoryName.StartsWith("Microsoft.AspNetCore"))
        {
            logLevel = LogLevel.Debug;
        }

        baseLogger.Log(logLevel, eventId, state, exception, formatter);
    }
}

这有点像黑客,但它有效地将记录为INFORMATION的ASP.NET事件转换为DEBUG事件,因此当您不需要它们时它们不会填满您的日志,但是您然后就是始终可以将您的日志级别设置为DEBUG以显示它们。

更新:

下面的Startup.cs文件演示了如何连接它:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Logging.Debug;

namespace WebApplication1
{
    public class LoggerProviderShim : ILoggerProvider
    {
        private ILoggerProvider baseLoggerProvider;

        public LoggerProviderShim(ILoggerProvider baseLoggerProvider)
        {
            this.baseLoggerProvider = baseLoggerProvider;
        }

        public ILogger CreateLogger(string categoryName)
        {
            return new LoggerShim(baseLoggerProvider.CreateLogger(categoryName), categoryName);
        }

        public void Dispose()
        {
            baseLoggerProvider.Dispose();
        }
    }

    public class LoggerShim : ILogger
    {
        private ILogger     baseLogger;
        private bool        treatInfoAsDebug;

        public LoggerShim(ILogger baseLogger, string categoryName)
        {
            this.baseLogger       = baseLogger;
            this.treatInfoAsDebug = categoryName != null && categoryName.StartsWith("Microsoft.AspNetCore.");
        }

        public IDisposable BeginScope<TState>(TState state)
        {
            return baseLogger.BeginScope(state);
        }

        public bool IsEnabled(LogLevel logLevel)
        {
            return baseLogger.IsEnabled(logLevel);
        }

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            if (treatInfoAsDebug && logLevel == LogLevel.Information)
            {
                logLevel = LogLevel.Debug;
            }

            baseLogger.Log(logLevel, eventId, state, exception, formatter);
        }
    }

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            var debugLogProvider = new DebugLoggerProvider();

            loggerFactory.AddProvider(debugLogProvider);
            //loggerFactory.AddProvider(new LoggerProviderShim(debugLogProvider));

            app.UseMvc();
        }
    }
}

我已在文件顶部添加了LoggerProviderShimLoggerShim类。 LoggerProviderShim旨在包装特定的记录器提供程序实现。对于此示例,我正在包裹DebugLoggerProviderLoggerShim用于包装(又名真实)记录器提供程序返回的包装记录器。

这里的想法是,不是将ILoggerProvider添加到Startup.Configure()中的记录器工厂,而是将实际提供程序包装在LoggerProviderShim中,然后将填充程序添加到记录仪工厂。

LoggerProviderShim的工作原理是从真实的记录器提供程序中获取真实的ILogger,然后将其包装在LoggerShim中,然后返回填充程序。 LoggerShim构造函数检查创建的记录器类别名称,以确定它是否应将INFORMATION事件记录为DEBUG。在这种情况下,我们通过查找来自ASP的记录器类别名称(例如以&#34为前缀的Microsoft)来为看起来像是来自ASP.NET CORE组件的事件执行此操作; .AspNetCore&#34;

记录器shim的Log()方法然后在调用底层真实记录器之前将这些记录器的INFORMATION loglevel更改为DEBUG。

通过在简单的WebAPI项目中包含此代码,您可以看到这一点:

  1. 确保appsettings.json中的日志级别设置为调试
  2. 运行应用程序并多次点击控制器端点。
  3. 在Visual Studio DEBUG输出面板中,请注意记录为信息的ASP.NET事件。
  4. 停止应用,然后在Startup.Configure()方法中注释掉第一个AddProvider()电话,取消注释第二个电话,然后重新测试该应用。
  5. 现在请注意,ASP.NET事件记录为 DEBUG 。垫片改变了事件级别。
  6. 您需要专门包装您关心的任何日志记录提供程序。在这个例子中,我包裹了DebugLogProvider。您需要单独为Application Insights或其他任何内容执行相同操作(我是否已经提到过这有点像黑客攻击)。

答案 2 :(得分:0)

可以通过设置&#34; MinimumLevel&#34;关闭http请求和响应的所有信息级别日志。在LoggerConfiguration中为&#34; Microsoft&#34;因为那些日志来自&#34; Microsoft.AspNetCore&#34; 。这可以在下面的代码中完成

Log.Logger = new LoggerConfiguration()
            .ReadFrom.Configuration(Configuration)
            .MinimumLevel.Override("Microsoft",LogEventLevel.Warning)
            .CreateLogger();

这也可以通过appsettings.json文件中的配置来完成,如下所示

"Serilog": {
"MinimumLevel": {
  "Default": "Debug",
  "Override": {
    "Microsoft": "Warning"
  }
},
"WriteTo": [
  {
    "Name": "Async",
    "Args": {
      "configure": [
        {
          "Name": "Console",
          "Args": {
            "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
          }
        },
        {
          "Name": "File",
          "Args": {
            "path": "Logs/log.txt",
            "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
            //"fileSizeLimitBytes": "1073741824",
            //"buffered": false,
            //"shared": false,
            "rollingInterval": "Minute"
            //"rollOnFileSizeLimit": false,
            //"retainedFileCountLimit": 31
          }
        }
      ]
    }
  }
]

}

相关问题