refactor: move Logging to GSS2.Core

This commit is contained in:
2026-02-04 07:31:56 +03:00
parent 99ebb79e0f
commit 201c67d46e
6 changed files with 13 additions and 7 deletions
-1
View File
@@ -35,6 +35,5 @@
<ItemGroup>
<ProjectReference Include="..\GSS2.Core\GSS2.Core.csproj" />
<ProjectReference Include="..\GSS2.Vulkan\GSS2.Vulkan.csproj" />
</ItemGroup>
</Project>
-111
View File
@@ -1,111 +0,0 @@
using Microsoft.Extensions.Logging.Abstractions;
namespace GSS2.Test.Logging;
public sealed class ConsoleFormatter : Microsoft.Extensions.Logging.Console.ConsoleFormatter
{
private static class Ansi
{
public const string Reset = "\x1b[0m";
public static string Color(ConsoleColor color) => color switch
{
ConsoleColor.Black => "\x1b[30m",
ConsoleColor.DarkRed => "\x1b[31m",
ConsoleColor.DarkGreen => "\x1b[32m",
ConsoleColor.DarkYellow => "\x1b[33m",
ConsoleColor.DarkBlue => "\x1b[34m",
ConsoleColor.DarkMagenta => "\x1b[35m",
ConsoleColor.DarkCyan => "\x1b[36m",
ConsoleColor.Gray => "\x1b[37m",
ConsoleColor.Red => "\x1b[91m",
ConsoleColor.Green => "\x1b[92m",
ConsoleColor.Yellow => "\x1b[93m",
ConsoleColor.Blue => "\x1b[94m",
ConsoleColor.Magenta => "\x1b[95m",
ConsoleColor.Cyan => "\x1b[96m",
ConsoleColor.White => "\x1b[97m",
_ => Reset
};
}
public ConsoleFormatter() : base(nameof(ConsoleFormatter))
{ }
public override void Write<TState>(in LogEntry<TState> logEntry, IExternalScopeProvider? scopeProvider, TextWriter textWriter)
{
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
var level = logEntry.LogLevel switch
{
LogLevel.Trace => "TRACE",
LogLevel.Debug => "DEBUG",
LogLevel.Information => "INFO",
LogLevel.Warning => "WARN",
LogLevel.Error => "ERROR",
LogLevel.Critical => "CRIT",
_ => "NONE",
};
var category = logEntry.Category;
var eventId = logEntry.EventId.Id;
var eventName = logEntry.EventId.Name;
var message = logEntry.Formatter?.Invoke(logEntry.State, logEntry.Exception);
if (Console.IsOutputRedirected)
{
textWriter.WriteLine($"[{timestamp}] [{level}] [{category}] {message}");
}
else
{
var levelColor = Ansi.Color(GetLogLevelColor(logEntry.LogLevel));
var categoryColor = Ansi.Color(ConsoleColor.Blue);
textWriter.Write('[');
textWriter.Write(timestamp);
textWriter.Write("] [");
textWriter.Write(levelColor);
textWriter.Write(level);
textWriter.Write(Ansi.Reset);
textWriter.Write("] [");
textWriter.Write(categoryColor);
textWriter.Write(category);
textWriter.Write(Ansi.Reset);
textWriter.Write("] [");
textWriter.Write(eventId);
textWriter.Write("] [");
textWriter.Write(eventName);
textWriter.Write("] ");
textWriter.WriteLine(message);
}
if (logEntry.Exception != null)
{
if (!Console.IsOutputRedirected)
Console.ForegroundColor = ConsoleColor.DarkRed;
textWriter.WriteLine(logEntry.Exception);
if (!Console.IsOutputRedirected)
Console.ResetColor();
}
}
private static void WriteColored(TextWriter writer, string text, ConsoleColor color)
{
var originalColor = Console.ForegroundColor;
Console.ForegroundColor = color;
writer.Write(text);
Console.ForegroundColor = originalColor;
}
private static ConsoleColor GetLogLevelColor(LogLevel level) => level switch
{
LogLevel.Trace => ConsoleColor.DarkGray,
LogLevel.Debug => ConsoleColor.Gray,
LogLevel.Warning => ConsoleColor.Yellow,
LogLevel.Error => ConsoleColor.Red,
LogLevel.Critical => ConsoleColor.DarkRed,
_ => Console.ForegroundColor
};
}
-55
View File
@@ -1,55 +0,0 @@
namespace GSS2.Test.Logging;
public sealed class FileLogger : ILogger
{
private readonly string _category;
private readonly string _filePath;
private static readonly object _lock = new();
private Queue<string> _linesToWrite = new Queue<string>();
public FileLogger(string category, string filePath)
{
_category = category;
_filePath = filePath;
}
#pragma warning disable CS8633 // Nullability in constraints for type parameter doesn't match the constraints for type parameter in implicitly implemented interface method'.
public IDisposable? BeginScope<TState>(TState state) => null;
#pragma warning restore CS8633 // Nullability in constraints for type parameter doesn't match the constraints for type parameter in implicitly implemented interface method'.
public bool IsEnabled(LogLevel logLevel) => true;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
var level = logLevel switch
{
LogLevel.Trace => "TRACE",
LogLevel.Debug => "DEBUG",
LogLevel.Information => "INFO",
LogLevel.Warning => "WARN",
LogLevel.Error => "ERROR",
LogLevel.Critical => "CRIT",
_ => "NONE",
};
var message = formatter(state, exception);
var line = $"[{timestamp}] [{level}] [{_category}] [{eventId.Id}] [{eventId.Name}] {message}";
lock (_lock)
{
_linesToWrite.Enqueue(line);
try
{
while (_linesToWrite.Count() > 0)
{
File.AppendAllText(_filePath, _linesToWrite.Dequeue() + Environment.NewLine);
if (exception != null)
File.AppendAllText(_filePath, exception + Environment.NewLine);
}
}
catch
{ }
}
}
}
-17
View File
@@ -1,17 +0,0 @@
namespace GSS2.Test.Logging;
public sealed class FileLoggerProvider : ILoggerProvider
{
private readonly string _filePath;
public FileLoggerProvider(string filePath, bool append = true)
{
_filePath = filePath;
if (!append && File.Exists(filePath))
File.Create(filePath);
}
public ILogger CreateLogger(string categoryName) => new FileLogger(categoryName, _filePath);
public void Dispose() { }
}
-95
View File
@@ -1,95 +0,0 @@
using LibCameraSharp;
namespace GSS2.Test.Logging;
public sealed class LibCameraLogSink : IDisposable
{
private readonly ILogger _logger;
private readonly ILogger _loggerCamera;
private readonly ILogger _loggerRPI;
private readonly ILogger _loggerDeviceEnumerator;
private readonly ILogger _loggerIPAProxy;
private readonly ILogger _loggerV4L2;
private readonly ILogger _loggerRPISTREAM;
private readonly ILogger _loggerWRAPPER;
private bool _disposedValue;
public LibCameraLogSink(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger("LibCamera");
_loggerCamera = loggerFactory.CreateLogger("LibCamera-Camera");
_loggerRPI = loggerFactory.CreateLogger("LibCamera-RPI");
_loggerDeviceEnumerator = loggerFactory.CreateLogger("LibCamera-DeviceEnumerator");
_loggerIPAProxy = loggerFactory.CreateLogger("LibCamera-IPAProxy");
_loggerV4L2 = loggerFactory.CreateLogger("LibCamera-V4L2");
_loggerRPISTREAM = loggerFactory.CreateLogger("LibCamera-RPISTREAM");
_loggerWRAPPER = loggerFactory.CreateLogger("LibCamera-WRAPPER");
Log.Initialize();
Log.SetLevel("Camera", Log.LogLevelEnum.DEBUG);
Log.SetLevel("RPI", Log.LogLevelEnum.DEBUG);
Log.SetLevel("DeviceEnumerator", Log.LogLevelEnum.DEBUG);
Log.SetLevel("IPAProxy", Log.LogLevelEnum.DEBUG);
Log.SetLevel("V4L2", Log.LogLevelEnum.DEBUG);
Log.SetLevel("RPISTREAM", Log.LogLevelEnum.DEBUG);
Log.SetLevel("WRAPPER", Log.LogLevelEnum.DEBUG);
Log.LogReceived += OnLogReceived;
}
private void OnLogReceived(object? sender, Log.LogEventArgs e)
{
if (_disposedValue)
return;
try
{
var level = MapLogLevel(e.Level);
var logger = e.Category switch
{
"Camera" => _loggerCamera,
"RPI" => _loggerRPI,
"DeviceEnumerator" => _loggerDeviceEnumerator,
"IPAProxy" => _loggerIPAProxy,
"V4L2" => _loggerV4L2,
"RPISTREAM" => _loggerRPISTREAM,
"WRAPPER" => _loggerWRAPPER,
_ => null
};
if (logger is not null && logger.IsEnabled(level))
logger.Log(level, new EventId(0, $"{e.ThreadId} {e.File}"), e, null, static (state, _) => $"{state.Message}");
else if (logger is null && _logger.IsEnabled(level))
_logger.Log(level, new EventId(0, $"{e.ThreadId} {e.File}"), e, null, static (state, _) => $"[{state.Category}] {state.Message}");
}
catch
{ }
}
private static LogLevel MapLogLevel(Log.LogLevelEnum level) => level switch
{
Log.LogLevelEnum.DEBUG => LogLevel.Debug,
Log.LogLevelEnum.INFO => LogLevel.Information,
Log.LogLevelEnum.WARN => LogLevel.Warning,
Log.LogLevelEnum.ERROR => LogLevel.Error,
Log.LogLevelEnum.FATAL => LogLevel.Critical,
_ => LogLevel.None
};
private void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
Log.LogReceived -= OnLogReceived;
}
_disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
+3 -2
View File
@@ -4,10 +4,11 @@ using Microsoft.Extensions.Logging.Console;
using Avalonia;
using Avalonia.OpenGL.Egl;
using GSS2.Core;
using GSS2.Core.Logging;
using GSS2.Core.Analysis.AmineContent.Database;
using GSS2.Test.Logging;
using ConsoleFormatter = GSS2.Core.Logging.ConsoleFormatter;
namespace GSS2.Test;
using ConsoleFormatter = GSS2.Test.Logging.ConsoleFormatter;
public class Program
{