using System.IO; using System.Text; using GFramework.Core.Abstractions.Logging; using GFramework.Core.Logging.Formatters; namespace GFramework.Core.Logging.Appenders; /// /// 文件日志输出器(线程安全) /// public sealed class FileAppender : ILogAppender, IDisposable { private readonly string _filePath; private readonly ILogFilter? _filter; private readonly ILogFormatter _formatter; private readonly object _lock = new(); private bool _disposed; private StreamWriter? _writer; /// /// 创建文件日志输出器 /// /// 日志文件路径 /// 日志格式化器 /// 日志过滤器(可选) /// 当文件路径为空或无效时抛出 /// 当无法创建或打开日志文件时抛出 public FileAppender( string filePath, ILogFormatter? formatter = null, ILogFilter? filter = null) { if (string.IsNullOrWhiteSpace(filePath)) throw new ArgumentException("File path cannot be null or whitespace.", nameof(filePath)); _filePath = filePath; _formatter = formatter ?? new DefaultLogFormatter(); _filter = filter; try { EnsureDirectoryExists(); InitializeWriter(); } catch { // 确保在初始化失败时清理资源 _writer?.Dispose(); _writer = null; throw; } } /// /// 释放资源 /// public void Dispose() { if (_disposed) return; lock (_lock) { _writer?.Flush(); _writer?.Dispose(); _writer = null; _disposed = true; } } /// /// 追加日志条目到文件 /// /// 日志条目 public void Append(LogEntry entry) { if (_disposed) throw new ObjectDisposedException(nameof(FileAppender)); if (_filter != null && !_filter.ShouldLog(entry)) return; var message = _formatter.Format(entry); lock (_lock) { _writer?.WriteLine(message); } } /// /// 刷新文件缓冲区 /// public void Flush() { lock (_lock) { _writer?.Flush(); } } private void EnsureDirectoryExists() { var directory = Path.GetDirectoryName(_filePath); if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) { Directory.CreateDirectory(directory); } } private void InitializeWriter() { _writer = new StreamWriter(_filePath, append: true, Encoding.UTF8) { AutoFlush = true }; } }