自定义ILogger Provider读取appSettings.json配置失败问题咨询
自定义ILoggerProvider配置失效问题排查与修复
问题1:appSettings.json配置无法传入Provider构造函数
原因分析
你的FileLoggerProvider第二个构造函数中硬编码覆盖了配置值,导致配置文件的设置被强行替换:
public FileLoggerProvider(FileLoggerOptions options) { options.Path = "C:/temp/log-{yyyy-MM-dd}.txt"; // 此行直接覆盖配置文件的Path值 _options = options; }
当通过IOptionsMonitor<FileLoggerOptions>注入时,会调用该构造函数,配置文件中Logging:File:Path的设置完全失效。
修复方案
删除硬编码覆盖的代码,保留构造函数对传入选项的赋值:
public FileLoggerProvider(FileLoggerOptions options) { _options = options; }
问题2:专属LogLevel设置被忽略
原因分析
日志系统的Provider专属LogLevel生效需要两个前提:
- 配置节点名称与Provider标识匹配(你的
File节点与FileLoggerProvider自动生成的标识一致,这部分没问题); - 自定义
ILogger必须正确读取日志系统的过滤规则,在IsEnabled方法中判断是否输出日志。
你当前的代码仅处理了Provider的配置注入,但未让自定义Logger集成日志系统的LogLevel过滤逻辑,导致Logging:File:LogLevel的设置被忽略。
修复方案
步骤1:修改FileLoggerProvider,注入ILoggerFactory获取过滤规则
在Provider中注入ILoggerFactory,复用系统内置的过滤逻辑:
public class FileLoggerProvider : ILoggerProvider { private readonly FileLoggerOptions _options; private readonly ILoggerFactory _loggerFactory; private IDisposable? _settingsChangeToken; public FileLoggerProvider(IOptionsMonitor<FileLoggerOptions> options, ILoggerFactory loggerFactory) : this(options.CurrentValue, loggerFactory) { _settingsChangeToken = options.OnChange(opt => { _options = opt; }); } public FileLoggerProvider(FileLoggerOptions options, ILoggerFactory loggerFactory) { _options = options; _loggerFactory = loggerFactory; } public ILogger CreateLogger(string categoryName) { return new FileLogger(categoryName, _options, _loggerFactory); } public void Dispose() { _settingsChangeToken?.Dispose(); } }
步骤2:实现FileLogger的IsEnabled方法,应用过滤规则
public class FileLogger : ILogger { private readonly string _categoryName; private readonly FileLoggerOptions _options; private readonly ILoggerFactory _loggerFactory; public FileLogger(string categoryName, FileLoggerOptions options, ILoggerFactory loggerFactory) { _categoryName = categoryName; _options = options; _loggerFactory = loggerFactory; } public bool IsEnabled(LogLevel logLevel) { // 复用系统过滤逻辑,判断当前日志级别是否符合配置 return _loggerFactory.CreateLogger(_categoryName).IsEnabled(logLevel); } public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) { if (!IsEnabled(logLevel)) return; // 实现你的文件写入逻辑 var logMessage = formatter(state, exception); File.AppendAllText(_options.Path ?? string.Empty, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{logLevel}] {_categoryName}: {logMessage}{Environment.NewLine}"); } public IDisposable? BeginScope<TState>(TState state) where TState : notnull { return null; } }
步骤3:修正注册代码,确保依赖注入完整
调整AddFileLogger扩展方法,保证ILoggerFactory能被正确注入:
public static ILoggingBuilder AddFileLogger(this ILoggingBuilder builder) { builder.AddConfiguration(); builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, FileLoggerProvider>(sp => { var optionsMonitor = sp.GetRequiredService<IOptionsMonitor<FileLoggerOptions>>(); var loggerFactory = sp.GetRequiredService<ILoggerFactory>(); return new FileLoggerProvider(optionsMonitor, loggerFactory); })); builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<FileLoggerOptions>, FileLoggerOptionsSetup>()); builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IOptionsChangeTokenSource<FileLoggerOptions>, LoggerProviderOptionsChangeTokenSource<FileLoggerOptions, FileLoggerProvider>>()); return builder; }
内容的提问来源于stack exchange,提问作者David Thielen
相关产品推荐
相关产品推荐

