You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MVC Core中AddLogging配置LoggerFilterOptions及自定义ILogger问询

Accessing LoggerFilterOptions in a Custom ILogger Implementation in ASP.NET Core

Let's break down exactly how you can work with LoggerFilterOptions when building your own custom logger or logger provider in ASP.NET Core. I know you're already familiar with how AddConfiguration binds your Logging config section to this options object—now let's dig into the implementation details for your custom logger.

1. Inject LoggerFilterOptions into Your Custom Provider/Logger

First off, when you call AddLogging, the framework automatically registers LoggerFilterOptions as a singleton in the DI container. That means you can directly inject it into your custom logger provider's constructor, then pass it along to your logger instances.

Here's a simple example of a custom provider that uses this:

public class MyCustomLoggerProvider : ILoggerProvider
{
    private readonly LoggerFilterOptions _filterOptions;
    private readonly ConcurrentDictionary<string, MyCustomLogger> _loggers = new();

    // Inject the pre-configured LoggerFilterOptions via constructor
    public MyCustomLoggerProvider(LoggerFilterOptions filterOptions)
    {
        _filterOptions = filterOptions;
    }

    public ILogger CreateLogger(string categoryName)
    {
        return _loggers.GetOrAdd(categoryName, name => new MyCustomLogger(name, _filterOptions));
    }

    public void Dispose() => _loggers.Clear();
}

Then your custom logger can use the options to handle log filtering correctly:

public class MyCustomLogger : ILogger
{
    private readonly string _categoryName;
    private readonly LoggerFilterOptions _filterOptions;

    public MyCustomLogger(string categoryName, LoggerFilterOptions filterOptions)
    {
        _categoryName = categoryName;
        _filterOptions = filterOptions;
    }

    public IDisposable BeginScope<TState>(TState state) => NullScope.Instance;

    public bool IsEnabled(LogLevel logLevel)
    {
        // Use the built-in filter logic from LoggerFilterOptions
        // First check if a custom filter delegate exists (from config or code)
        var filterResult = _filterOptions.Filter?.Invoke(_categoryName, logLevel);
        // Fall back to the minimum level if no filter applies
        return filterResult ?? logLevel >= _filterOptions.MinLevel;
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        if (!IsEnabled(logLevel)) return;

        // Your custom logging logic here (write to file, external service, etc.)
        var logMessage = formatter(state, exception);
        Console.WriteLine($"[Custom Logger] {_categoryName} | {logLevel}: {logMessage}");
    }
}

2. Understand How LoggerFilterOptions Maps to Your Config

When you call AddConfiguration(configuration.GetSection("Logging")), the framework parses your config into LoggerFilterOptions properties:

  • MinLevel: Sets the default minimum log level for all categories (defaults to Information if not specified).
  • Filter: A delegate that applies category-specific rules (like the Microsoft.AspNetCore: Warning rule in typical appsettings).

For example, this config:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "MyApp.Services": "Debug"
    }
  }
}

Gets translated into a filter delegate that returns true for Debug+ levels in MyApp.Services, and Information+ for everything else. Your custom logger's IsEnabled method will automatically respect these rules when using the Filter delegate.

3. Dynamic Filter Updates (Optional)

If you need to adjust log levels at runtime (without restarting the app), you can resolve LoggerFilterOptions from DI and modify its properties directly. For example, in an admin controller:

[ApiController]
[Route("admin/logging")]
public class LoggingAdminController : ControllerBase
{
    private readonly LoggerFilterOptions _filterOptions;

    public LoggingAdminController(LoggerFilterOptions filterOptions)
    {
        _filterOptions = filterOptions;
    }

    [HttpPost("set-min-level")]
    public IActionResult SetGlobalMinLevel(LogLevel newLevel)
    {
        // Wrap in a lock if you're modifying this from multiple threads
        lock (_filterOptions)
        {
            _filterOptions.MinLevel = newLevel;
        }
        return Ok("Global log level updated");
    }
}

Just make sure your IsEnabled method checks the options every time (don't cache the result) so it picks up changes immediately.

4. Key Best Practices

  • Thread Safety: LoggerFilterOptions isn't thread-safe by default. If you're modifying it at runtime, use locks or thread-safe wrappers to prevent race conditions.
  • Leverage Built-In Logic: Don't reimplement category-based filtering yourself—let the Filter delegate handle it. It already correctly applies your config rules.
  • Avoid Caching IsEnabled Results: Always check IsEnabled right before writing a log entry, especially if you might update filters dynamically.

内容的提问来源于stack exchange,提问作者Henrik Poulsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:43:30