2025-11-08 15:10:44 +08:00

162 lines
4.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Serilog;
using Serilog.Core;
using Serilog.Events;
using Serilog.Sinks.SystemConsole.Themes;
namespace BangumiRenamer.Utils;
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.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();
}
}
}
}