using GFramework.Core.Abstractions.Logging; using GFramework.Core.Logging.Appenders; namespace GFramework.Core.Logging; /// /// 可配置的 Logger 工厂。 /// internal sealed class ConfigurableLoggerFactory : ILoggerFactory, IDisposable { private readonly ILogAppender[] _appenders; private readonly LoggingConfiguration _config; private int _disposed; /// /// 初始化一个基于日志配置创建输出管线的工厂实例。 /// /// 日志配置。 public ConfigurableLoggerFactory(LoggingConfiguration config) { _config = config ?? throw new ArgumentNullException(nameof(config)); // 反序列化输入可能显式把集合写成 null,这里统一归一化为可安全枚举的空集合。 _config.Appenders ??= []; _config.LoggerLevels ??= new Dictionary(StringComparer.Ordinal); _appenders = _config.Appenders.Select(LoggingConfigurationLoader.CreateAppender).ToArray(); } /// /// 释放内部 Appender 持有的资源。 /// public void Dispose() { if (Interlocked.Exchange(ref _disposed, 1) != 0) { return; } foreach (var appender in _appenders) { switch (appender) { case AsyncLogAppender asyncLogAppender: asyncLogAppender.Dispose(); break; case IDisposable disposable: disposable.Dispose(); break; } } } /// /// 为指定名称创建日志记录器,并应用最匹配的命名空间级别配置。 /// /// 日志记录器名称。 /// 调用方要求的最小日志级别下限;最终级别不会低于该值。 /// 可写入日志的记录器实例。 /// /// 当配置文件与调用方同时提供默认级别时,会取两者中更严格的那一个; /// 若命中更具体的命名空间级别覆盖,则以该覆盖配置为准。 /// public ILogger GetLogger(string name, LogLevel minLevel = LogLevel.Info) { var effectiveLevel = _config.MinLevel > minLevel ? _config.MinLevel : minLevel; var bestMatchLength = -1; foreach (var kvp in _config.LoggerLevels) { var isExactMatch = string.Equals(name, kvp.Key, StringComparison.Ordinal); if (isExactMatch) { effectiveLevel = kvp.Value; break; } var isPrefixMatch = name.StartsWith(kvp.Key + ".", StringComparison.Ordinal); if (isPrefixMatch && kvp.Key.Length > bestMatchLength) { // 多个命名空间前缀都能命中时,最长前缀代表最具体的配置。 bestMatchLength = kvp.Key.Length; effectiveLevel = kvp.Value; } } if (_appenders.Length == 0) { return new ConsoleLogger(name, effectiveLevel); } if (_appenders.Length == 1 && _appenders[0] is ConsoleAppender) { return new ConsoleLogger(name, effectiveLevel); } return new CompositeLogger(name, effectiveLevel, _appenders); } }