。NET Core-如何根据类别进行过滤?

问题描述 投票:0回答:2

所以我有一个基本的自定义记录器,并按以下步骤进行设置:

public static IWebHost CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseIISIntegration()
        .ConfigureLogging((hostingContext, logging) =>
        {
            logging.AddConsole();
            logging.AddCustomLogger().AddFilter<CustomLoggerProvider>(typeof(CustomLogEntry).ToString(), LogLevel.None); // My custom logger
            logging.SetMinimumLevel(LogLevel.Trace);
        }).Build();
}

我的理解是,.AddFilter意味着仅记录器的

typeof(CustomLogEntry) 

实际上应该注销到我的自定义记录器。不过,事实似乎并非如此!

添加实际记录器的扩展名非常简单:

public static ILoggingBuilder AddCustomLogger(this ILoggingBuilder builder)
    {
        builder.AddConfiguration();
        builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, CustomLoggerProvider>());
        builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<CustomLoggerOptions>, CustomLoggerOptionsSetup>());
        builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IOptionsChangeTokenSource<LoggerOptions>, CustomLoggerProviderOptionsChangeTokenSource<CustomLoggerOptions, CustomLoggerProvider>>());
        return builder;
    }

我的自定义记录器也非常简单:

public class CustomLogger : ILogger
{
    public CustomLoggerProvider Provider { get; private set; }
    public string Category { get; private set; }

    public Logger(CustomLoggerProvider provider, string category)
    {
        Provider = provider;
        Category = category;
    }

    public IDisposable BeginScope<T>(T item)
    {
        return Provider.ScopeProvider.Push(item);
    }

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

    public void Log<T>(LogLevel logLevel, EventId eventId, T item, Exception exception, Func<T, Exception, string> formatter)
    {
        if (IsEnabled(logLevel))
        {
            // Generate the log entry
            CustomLogEntry logEntry = new CustomLogEntry();

            // removed for brevity...

            // Write the log out to the provider!
            Provider.WriteLog(logEntry);
        }
    }
}

和提供者:

[ProviderAlias("Custom")]
public class CustomLoggerProvider : ILoggerProvider, IDisposable, ISupportExternalScope
{
    private ConcurrentQueue<CustomLogEntry> _logQueue = new ConcurrentQueue<CustomLogEntry>();
    private readonly IDisposable _settingsChangeToken;
    private readonly CustomLogger _customLogger;
    private CustomLoggerOptions _settings;
    private bool _terminated = false;

    public IExternalScopeProvider ScopeProvider { get; set; }

    public CustomLoggerProvider(IOptionsMonitor<LoggerOptions> settings, IConfiguration configuration) : this(settings.CurrentValue, configuration)
    {
        // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/change-tokens
        _settingsChangeToken = settings.OnChange(options =>
        {
            _settings = options;
        });
    }

    public CustomLoggerProvider(CustomLoggerOptions settings, IConfiguration configuration)
    {
        _settings = settings;
        _customLogger = new CustomLogger(this, typeof(CustomLogEntry).ToString());

        ProcessQueue();
    }

    public ILogger CreateLogger(string categoryName)
    {
        return _customLogger;
    }

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

    public void WriteLog(LogEntry logEntry)
    {
        _logQueue.Enqueue(logEntry);
    }
    private void ProcessQueue()
    {
        Task.Run(async () =>
        {
            while (!_terminated)
            {
                try
                {
                    // chew up the queue
                    if (_logQueue.TryDequeue(out CustomLogEntry logEntry))
                    {
                        // Do work, removed for brevity
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
            }
        });
    }

    #region IDisposable Support
    private bool disposedValue = false; // To detect redundant calls

    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                // TODO: dispose managed state (managed objects).
                _terminated = true;
            }

            // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
            // TODO: set large fields to null.

            disposedValue = true;
        }
    }

    // This code added to correctly implement the disposable pattern.
    void IDisposable.Dispose()
    {
        // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        Dispose(true);
    }
    #endregion

    #region ISupportExternalScope Support
    public void SetScopeProvider(IExternalScopeProvider scopeProvider)
    {
        ScopeProvider = scopeProvider;
    }
    #endregion
}

因此,在将它们放在一起并进行了测试之后,我看到每个LogLevel.Trace或更高版本的日志都记录到CustomLogger中。

我想做的是,只有特定类别的日志实际注销到自定义提供程序。或者换句话说,根据类别过滤要注销的日志提供程序。

我无法做到吗?我是否会误解.AddFilter实际如何工作? (可能是,哈哈)

我怀疑我的CustomLoggerProvider.IsEnabled某种程度上需要检查传入的日志类别是否正确,但我只是不知道如何实现此目的。

我将不胜感激任何指针。

logging .net-core asp.net-core-2.1
2个回答
0
投票

AddFilter的第一个参数是要应用它的名称空间。目前,您正在传递nameof(CustomLogEntry),该命令将无法使用。实质上,这就是说only


0
投票

所以这就是我最终要做的:

© www.soinside.com 2019 - 2024. All rights reserved.