Как отключить ведение журнала, выполненное с помощью основной структуры ASP.NET

Как отключить ведение журнала, выполненное ASP.NET для каждого запроса, например.

INFO 09:38:41 Профиль пользователя доступен. Использование "C:\Users\xxxx xxxx\AppData\Local\ASP.NET\DataProtection-Keys" в качестве ключевого репозитория и Windows DPAPI для шифрования ключей в состоянии покоя.
DEBUG 09:38:41 Хостинг начиная с DEBUG 09:38:41 Хостинг начался
INFO 09:38:41 Запрос запуска HTTP/1.1 GET http://localhost:23369/
INFO 09:38:41 Запрос на запуск HTTP/1.1 DEBUG http://localhost:23369/ text/html DEBUG 09:38:41 Запросы DEBUG не поддерживаются
DEBUG 09:38:41 Путь запроса/не соответствует поддерживаемому типу файлов
DEBUG 09:38:41 Запрос успешно сопоставил маршрут с именем 'default' и template '{controller = Home}/{action = Index}/{id?}'. DEBUG 09:38:41 Запрос успешно сопоставил маршрут с именем 'default' и template '{controller = Home}/{action = Index}/{id?}'. DEBUG 09:38:41 Выполнение действий Forums.Controllers.HomeController.Index
DEBUG 09:38:41 Выполнение действий Forums.Controllers.HomeController.Index
INFO 09:38:41 Выполнение метода действий Forums.Controllers.HomeController.Index с аргументами() - ModelState is Valid '
INFO 09:38:41 Выполнение действия метода Forums.Controllers.HomeController.Index
..

Я еще не мог найти, как я могу отключить это отключение...

Это мой метод Configure в классе Startup:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddProvider(new Log4NetProvider());

    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");

        // For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859
        try
        {
            using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
                .CreateScope())
            {
                serviceScope.ServiceProvider.GetService<ApplicationDbContext>()
                     .Database.Migrate();
            }
        }
        catch { }
    }

    app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear());

    app.UseStaticFiles();

    app.UseIdentity();

    // To configure external authentication please see http://go.microsoft.com/fwlink/?LinkID=532715

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

И это мой файл project.json:

"dependencies": {
  "EntityFramework.Commands": "7.0.0-rc1-final",
  "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
  "log4net": "2.0.5",
  "Microsoft.AspNet.Authentication.Cookies": "1.0.0-rc1-final",
  "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-rc1-final",
  "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final",
  "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
  "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
  "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final",
  "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
  "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
  "Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final",
  "Microsoft.Extensions.CodeGenerators.Mvc": "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.Configuration.UserSecrets": "1.0.0-rc1-final",
  "Microsoft.Extensions.Logging": "1.0.0-rc1-final",
  "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-rc1-final"
},

"commands": {
  "web": "Microsoft.AspNet.Server.Kestrel",
  "ef": "EntityFramework.Commands"
},

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

Update:
Мой провайдер log4net был взят здесь

Ответы

Ответ 1

Поскольку новая инфраструктура ведения журнала используется (по дизайну) самой asp.net(а также другим кодом поставщика), она выполняет реализацию ILoggerProvider, чтобы решить, хочет ли он регистрировать этот источник или нет.

Здесь приведено исправление для log4net, которое добавляет базовую фильтрацию источника:

public class Log4NetProvider : ILoggerProvider
{
    private static readonly NoopLogger _noopLogger = new NoopLogger();
    private readonly Func<string, bool> _sourceFilterFunc;
    private readonly ConcurrentDictionary<string, Log4NetLogger> _loggers = new ConcurrentDictionary<string, Log4NetLogger>();

    public Log4NetProvider(Func<string, bool> sourceFilterFunc = null)
    {
        _sourceFilterFunc = sourceFilterFunc != null ? sourceFilterFunc : x => true;
    }

    public ILogger CreateLogger(string name)
    {
        if (!_sourceFilterFunc(name))
            return _noopLogger;

        return _loggers.GetOrAdd(name, x => new Log4NetLogger(name));
    }

    public void Dispose()
    {
        _loggers.Clear();
    }

    private class NoopLogger : ILogger
    {
        public IDisposable BeginScopeImpl(object state)
        {
            return null;
        }

        public bool IsEnabled(LogLevel logLevel)
        {
            return false;
        }

        public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
        {
        }
    }
}

И Log4NetAspExtensions:

public static void ConfigureLog4Net(this IApplicationEnvironment appEnv, string configFileRelativePath)
{
    GlobalContext.Properties["appRoot"] = appEnv.ApplicationBasePath;
    XmlConfigurator.Configure(new FileInfo(Path.Combine(appEnv.ApplicationBasePath, configFileRelativePath)));
}

public static void AddLog4Net(this ILoggerFactory loggerFactory, Func<string, bool> sourceFilterFunc = null)
{
    loggerFactory.AddProvider(new Log4NetProvider(sourceFilterFunc));
}

public static void AddLog4Net(this ILoggerFactory loggerFactory)
{
    loggerFactory.AddLog4Net(null);
}

Возможное использование (в Startup.cs):

public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv, ILoggerFactory loggerFactory)
{
    appEnv.ConfigureLog4Net("log4net.xml");

    loggerFactory.AddLog4Net(x => !x.StartsWith("Microsoft."));
}

Ответ 2

Я не уверен, что у меня что-то не хватает, но разве вы просто не хотите поднимать уровень журнала для журналов Microsoft?

Изменить appsettings.json (принимает .AddJsonFile("appsettings.json", ...))

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Trace",
      "System": "Information",
      "Microsoft": "Information"

Для

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Trace",
      "System": "Information",
      "Microsoft": "None"

Или такая же модификация через переменные среды (предполагается .AddEnvironmentVariables())

Logging:LogLevel:Microsoft=None

Вы также можете быть более конкретным, следующее сокращает большинство записей, но оставляет Microsoft.AspNetCore.Hosting.Internal.WebHost в Information.

"Microsoft": "Information",  
"Microsoft.AspNetCore.Mvc.Internal": "Warning",
"Microsoft.AspNetCore.Authentication":  "Warning"

Приложения, если это не работает для log4net

Ответ 3

В и перед ASP.NET 5 RC1 (теперь ASP.NET Core 1.0) вы можете сделать это через регистратор factory, т.е.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // completely disable logging or use one of the other levels, such as Error, Critical, Warning etc. 
    loggerFactory.MinimumLevel = LogLevel.None;
}

Однако, с текущей ветвью (еще не выпущенной, но доступной через ночные сборки), это было удалено. Теперь вам нужно передать LogLevel для каждого провайдера. Обычно это делается с помощью метода расширения.

Для встроенного консольного регистратора это будет loggerFactory.AddConsole(minimumLevel: LogLevel.Warning);, например.

Поскольку ваш поставщик журналов является настраиваемым, вам придется настроить его самостоятельно. Посмотрите, как это делает консольный регистратор. Он передает делегату поставщика, который выполняет фильтрацию.

От Источник GitHub:

public static ILoggerFactory AddConsole(
    this ILoggerFactory factory,
    LogLevel minLevel,
    bool includeScopes)
{
    factory.AddConsole((category, logLevel) => logLevel >= minLevel, includeScopes);
    return factory;
}

Конечно, вместо передачи делегата вы также можете напрямую установить уровень журнала log4net.

Обновить. Чтобы расширить то, что я указал в комментариях

ILoggerProvider - это только обертка вокруг реальной структуры ведения журнала. В простом случае ConsoleLoggerProvider нет рамки, поскольку все позади нее, просто простой вызов Console.WriteLine.

В случае log4net в примере видно, что ведение журнала может быть включено для каждого уровня. Это невозможно с абстракцией основного регистратора .NET Core, описанной выше, поскольку абстракция не выполняет фильтрацию.

В log4net ILoggerProvider можно было бы просто маршрутизировать все уровни журнала в библиотеку сети log4net и фильтровать его.

Основываясь на связанной проблеме GitHub @haim770, у вас есть SourceContext для фильтрации, и если у log4net нет концепции SourceContext, вам придется реализовать это в провайдере. Если у него есть концепция SourceContext, поставщик должен перенаправить/перевести его в структуру, которую ожидает log4net.

Как вы можете видеть, сам журнал всегда остается не в курсе внутренних особенностей и деталей реализации ASP.NET. Log4NetProvider не может и не должен, потому что задача состоит в том, чтобы перевести/обернуть вокруг этого api. Провайдеры - это просто абстракции, поэтому нам не нужно просачивать детали реализации в библиотеку, например.

Ответ 4

Если вы используете Serilog для ведения журнала .Net core, вы можете обновить файл appsettings.json, чтобы установить уровни журналов следующим образом:

"Serilog": {
  "MinimumLevel": {
    "Default": "Verbose",
    "Override": {
      "Microsoft": "Error",
      "System": "Error"
    }
  },
  "Properties": {
    "Application": "your-app"
  }
}

Это позволяет вам регистрировать ошибки только в System/Microsoft при регистрации всего остального, как вам хотелось бы.