using Serilog; using Serilog.Core; using Serilog.Events; using Serilog.Sinks.SystemConsole.Themes; namespace BangumiRenamer.Utils; public sealed class Log { private static readonly Lazy _instance = new Lazy(() => new Log()); private Logger _logger; private bool _isInitialized = false; private readonly object _lockObject = new object(); public static Log Instance => _instance.Value; public static ILogger Logger => Instance._logger; private Log() { } /// /// 初始化日志配置 /// public static void Initialize(Action configure = null) { Instance.InitializeInternal(configure); } private void InitializeInternal(Action configure = null) { lock (_lockObject) { if (_isInitialized) { Warn("日志系统已经初始化过"); return; } var config = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.Console( outputTemplate: "[{Timestamp:HH:mm:ss}][{Level:u3}] {Message:lj}{NewLine}{Exception}", theme: AnsiConsoleTheme.Sixteen ) .Enrich.FromLogContext() .Enrich.WithThreadId(); configure?.Invoke(config); _logger = config.CreateLogger(); _isInitialized = true; Info("日志系统初始化完成"); } } // 静态快捷方法 - 使用更简短的名称 public static void Debug(string message, params object[] properties) => Instance.EnsureAndLog(LogEventLevel.Debug, message, properties); public static void Info(string message, params object[] properties) => Instance.EnsureAndLog(LogEventLevel.Information, message, properties); public static void Warn(string message, params object[] properties) => Instance.EnsureAndLog(LogEventLevel.Warning, message, properties); public static void Error(string message, params object[] properties) => Instance.EnsureAndLog(LogEventLevel.Error, message, properties); public static void Error(Exception ex, string message, params object[] properties) => Instance.EnsureAndLog(ex, message, properties); public static void Fatal(string message, params object[] properties) => Instance.EnsureAndLog(LogEventLevel.Fatal, message, properties); // 实例方法 private void EnsureAndLog(LogEventLevel level, string message, object[] properties) { EnsureInitialized(); _logger.Write(level, message, properties); } private void EnsureAndLog(Exception ex, string message, object[] properties) { EnsureInitialized(); _logger.Error(ex, message, properties); } /// /// 为特定类型创建Logger /// public static ILogger ForContext() { Instance.EnsureInitialized(); return Instance._logger.ForContext(); } /// /// 为特定源创建Logger /// public static ILogger ForContext(string source) { Instance.EnsureInitialized(); return Instance._logger.ForContext("SourceContext", source); } /// /// 开始一个带属性的日志上下文 /// public static IDisposable BeginScope(string propertyName, object value) { Instance.EnsureInitialized(); return Serilog.Context.LogContext.PushProperty(propertyName, value); } /// /// 开始多个属性的日志上下文 /// public static IDisposable BeginScope(params (string Name, object Value)[] properties) { Instance.EnsureInitialized(); var disposables = properties.Select(p => Serilog.Context.LogContext.PushProperty(p.Name, p.Value)).ToArray(); return new DisposableGroup(disposables); } /// /// 关闭并刷新日志 /// public static void Close() { Instance._logger?.Dispose(); Serilog.Log.CloseAndFlush(); Instance._isInitialized = false; } private void EnsureInitialized() { if (!_isInitialized) { InitializeInternal(); } } // 辅助类:用于同时释放多个IDisposable private class DisposableGroup : IDisposable { private readonly IDisposable[] _disposables; public DisposableGroup(IDisposable[] disposables) { _disposables = disposables; } public void Dispose() { foreach (var disposable in _disposables) { disposable?.Dispose(); } } } }