添加日志系统

This commit is contained in:
limil 2025-11-01 20:42:58 +08:00
parent 4f021d5a3e
commit d784357fe5
5 changed files with 173 additions and 6 deletions

View File

@ -18,6 +18,9 @@
<ItemGroup>
<PackageReference Include="NativeFileDialogSharp" Version="0.5.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="Serilog" Version="4.3.0" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="TMDbLib" Version="2.3.0" />
</ItemGroup>

164
Src/Log/Log.cs Normal file
View File

@ -0,0 +1,164 @@
using Serilog.Sinks.SystemConsole.Themes;
namespace BangumiRenamer;
using Serilog;
using Serilog.Core;
using Serilog.Events;
public sealed class Log
{
private static readonly Lazy<Log> _instance = new Lazy<Log>(() => 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() { }
/// <summary>
/// 初始化日志配置
/// </summary>
public static void Initialize(Action<LoggerConfiguration> configure = null)
{
Instance.InitializeInternal(configure);
}
private void InitializeInternal(Action<LoggerConfiguration> 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.WithProperty("Application", "MyApp")
.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);
}
/// <summary>
/// 为特定类型创建Logger
/// </summary>
public static ILogger ForContext<T>()
{
Instance.EnsureInitialized();
return Instance._logger.ForContext<T>();
}
/// <summary>
/// 为特定源创建Logger
/// </summary>
public static ILogger ForContext(string source)
{
Instance.EnsureInitialized();
return Instance._logger.ForContext("SourceContext", source);
}
/// <summary>
/// 开始一个带属性的日志上下文
/// </summary>
public static IDisposable BeginScope(string propertyName, object value)
{
Instance.EnsureInitialized();
return Serilog.Context.LogContext.PushProperty(propertyName, value);
}
/// <summary>
/// 开始多个属性的日志上下文
/// </summary>
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);
}
/// <summary>
/// 关闭并刷新日志
/// </summary>
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();
}
}
}
}

View File

@ -9,7 +9,7 @@ public class EmbededResourceViewer
var names = ResourceLoader.GetAllResNames();
foreach (var name in names)
{
Console.WriteLine(name);
Log.Info(name);
}
}
}

View File

@ -64,7 +64,7 @@ public static class FolderCloner
}
catch (Exception ex)
{
Console.WriteLine($"Clone失败 {ex.Message}");
Log.Error(ex, "Clone");
}
}
}

View File

@ -53,7 +53,7 @@ public static class ShowCompletionChecker
var checkPath = dir.Path;
var shows = FindShows(checkPath);
Console.WriteLine($"Total Shows: {shows.Count}");
Log.Info($"Total Shows: {shows.Count}");
var client = new TMDbClient(
apiKey: Config.Default.Get<TMDBConfig>().ApiKey ,
@ -69,7 +69,7 @@ public static class ShowCompletionChecker
var info = result.Results.FirstOrDefault();
if (info == null)
{
Console.WriteLine($"找不到对应的TV{t.title}");
Log.Error($"找不到对应的TV{t.title}");
continue;
}
foreach (var session in t.sessions)
@ -77,7 +77,7 @@ public static class ShowCompletionChecker
var sessionInfo = client.GetTvSeasonAsync(info.Id, session.id).Result;
if (sessionInfo == null)
{
Console.WriteLine($"季度对不上,可能找错了:{t.title} -> {info.OriginalName}");
Log.Error($"季度对不上,可能找错了:{t.title} -> {info.OriginalName}");
break;
}
foreach (var episode in sessionInfo.Episodes)
@ -90,6 +90,6 @@ public static class ShowCompletionChecker
}
}
}
Console.Write(output);
Log.Info(output.ToString());
}
}