using System.Runtime.CompilerServices; using Newtonsoft.Json; using Serilog; using Serilog.Context; using Serilog.Core; using Serilog.Events; using Serilog.Sinks.SystemConsole.Themes; namespace BangumiRenamer.Utils; public interface ILog { public void Debug(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = ""); public void Info(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = ""); public void Warn(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = ""); public void Error(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = ""); public void Error(Exception ex, string message); } public sealed class Log : ILog { public enum LogLevel { Error, Warn, Info, Debug, } [ConfigItem("Log")] public class LogConfig : IConfigItem { [JsonIgnore] public LogLevel Level = LogLevel.Debug; [JsonProperty("Level")] private string _level; public bool ToConsole = true; public bool ToFile = false; public string LogFilePath; public void AfterLoad() { if (!string.IsNullOrEmpty(_level)) LogLevel.TryParse(_level, out Level); } public void BeforeSave() { _level = Level.ToString(); } } public static ILog G => _G; public static Log _G { private get; set; } private LogConfig _config; private Logger _logger; public Log(LogConfig config) { _config = config; } public bool Init() { if (_config == null) return false; var config = new LoggerConfiguration(); switch (_config.Level) { case LogLevel.Error: config.MinimumLevel.Error(); break; case LogLevel.Warn: config.MinimumLevel.Warning(); break; case LogLevel.Debug: config.MinimumLevel.Debug(); break; case LogLevel.Info: default: config.MinimumLevel.Information(); break; } var outputTemplate = "[{Timestamp:HH:mm:ss}][{CallerPlace}][{Level:u3}] {Message:lj}{NewLine}{Exception}"; if (_config.ToConsole) { config.WriteTo.Console( outputTemplate: outputTemplate, theme: AnsiConsoleTheme.Sixteen ); } if (_config.ToFile) { if (string.IsNullOrEmpty(_config.LogFilePath)) { return false; } config.WriteTo.File( outputTemplate: outputTemplate, path: _config.LogFilePath ); } config.Enrich.FromLogContext() .Enrich.WithThreadId(); try { _logger = config.CreateLogger(); } catch (Exception) { return false; } return true; } // 静态快捷方法 - 使用更简短的名称 public void Debug(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "") { using (LogContext.PushProperty("CallerPlace", Path.GetFileNameWithoutExtension(callerFilePath) + "::" + callerMemberName)) { _logger.Write(LogEventLevel.Debug, message); } } public void Info(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "") { using (LogContext.PushProperty("CallerPlace", Path.GetFileNameWithoutExtension(callerFilePath) + "::" + callerMemberName)) { _logger.Write(LogEventLevel.Information, message); } } public void Warn(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "") { using (LogContext.PushProperty("CallerPlace", Path.GetFileNameWithoutExtension(callerFilePath) + "::" + callerMemberName)) { _logger.Write(LogEventLevel.Warning, message); } } public void Error(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "") { using (LogContext.PushProperty("CallerPlace", Path.GetFileNameWithoutExtension(callerFilePath) + "::" + callerMemberName)) { _logger.Write(LogEventLevel.Error, message); } } public void Error(Exception ex, string message) => WriteLog(ex, message); private void WriteLog(Exception ex, string message) { _logger.Error(ex, message); } }