2025-08-07 22:34:25 +03:00
|
|
|
using System.Collections.Concurrent;
|
2025-05-05 20:43:28 +03:00
|
|
|
using System.Reflection;
|
2025-01-05 17:05:23 +03:00
|
|
|
using Nebula.Shared.Services.Logging;
|
2024-12-22 16:38:47 +03:00
|
|
|
|
2025-01-05 17:05:23 +03:00
|
|
|
namespace Nebula.Shared.Services;
|
2024-12-22 16:38:47 +03:00
|
|
|
|
|
|
|
|
[ServiceRegister]
|
|
|
|
|
public class DebugService : IDisposable
|
|
|
|
|
{
|
2025-05-05 21:28:09 +03:00
|
|
|
public static bool DoFileLog;
|
|
|
|
|
|
|
|
|
|
private readonly string _path =
|
|
|
|
|
Path.Combine(FileService.RootPath, "log", Assembly.GetEntryAssembly()?.GetName().Name ?? "App");
|
2025-08-07 22:34:25 +03:00
|
|
|
|
2025-05-05 20:43:28 +03:00
|
|
|
public DebugService()
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-05-05 21:28:09 +03:00
|
|
|
ClearLog();
|
2025-08-07 22:34:25 +03:00
|
|
|
Root = new ServiceLogger("Root", _path);
|
|
|
|
|
Root.GetLogger("DebugService")
|
|
|
|
|
.Log("Initializing debug service " + (DoFileLog ? "with file logging" : "without file logging"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ServiceLogger Root { get; }
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
Root.Dispose();
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
|
2025-05-05 20:43:28 +03:00
|
|
|
public ILogger GetLogger(string loggerName)
|
2025-01-14 22:10:16 +03:00
|
|
|
{
|
2025-05-05 20:43:28 +03:00
|
|
|
return Root.GetLogger(loggerName);
|
|
|
|
|
}
|
2025-01-19 22:52:29 +03:00
|
|
|
|
2025-05-05 20:43:28 +03:00
|
|
|
public ILogger GetLogger(object objectToLog)
|
|
|
|
|
{
|
|
|
|
|
return Root.GetLogger(objectToLog.GetType().Name);
|
2025-01-14 22:10:16 +03:00
|
|
|
}
|
|
|
|
|
|
2025-05-05 21:28:09 +03:00
|
|
|
private void ClearLog()
|
|
|
|
|
{
|
2025-08-07 22:34:25 +03:00
|
|
|
if (!Directory.Exists(_path))
|
2025-05-05 21:28:09 +03:00
|
|
|
return;
|
|
|
|
|
var di = new DirectoryInfo(_path);
|
|
|
|
|
|
2025-08-07 22:34:25 +03:00
|
|
|
foreach (var file in di.GetFiles()) file.Delete();
|
|
|
|
|
foreach (var dir in di.GetDirectories()) dir.Delete(true);
|
2025-05-05 21:28:09 +03:00
|
|
|
}
|
2025-05-05 20:43:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public enum LoggerCategory
|
|
|
|
|
{
|
|
|
|
|
Log,
|
|
|
|
|
Debug,
|
|
|
|
|
Error
|
|
|
|
|
}
|
2024-12-22 16:38:47 +03:00
|
|
|
|
2025-05-05 20:43:28 +03:00
|
|
|
internal class ServiceLogger : ILogger
|
|
|
|
|
{
|
2025-05-05 21:28:09 +03:00
|
|
|
private readonly string _directory;
|
2025-08-07 22:34:25 +03:00
|
|
|
private readonly string _path;
|
|
|
|
|
|
2025-05-05 21:28:09 +03:00
|
|
|
public ServiceLogger(string category, string directory)
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-05-05 21:28:09 +03:00
|
|
|
_directory = directory;
|
2025-05-05 20:43:28 +03:00
|
|
|
Category = category;
|
|
|
|
|
|
2025-05-05 21:28:09 +03:00
|
|
|
if (!DebugService.DoFileLog) return;
|
2025-08-07 22:34:25 +03:00
|
|
|
|
|
|
|
|
if (!Directory.Exists(directory)) Directory.CreateDirectory(directory);
|
2025-06-19 21:12:42 +03:00
|
|
|
|
|
|
|
|
_path = Path.Combine(directory, $"{Category}.log");
|
2025-08-07 22:34:25 +03:00
|
|
|
|
2025-06-19 21:12:42 +03:00
|
|
|
File.Create(_path).Dispose();
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
|
2025-08-07 22:34:25 +03:00
|
|
|
public ServiceLogger? Root { get; private set; }
|
|
|
|
|
|
2025-05-05 20:43:28 +03:00
|
|
|
public string Category { get; init; }
|
2025-08-07 22:34:25 +03:00
|
|
|
private ConcurrentDictionary<string, ServiceLogger> Childs { get; } = new();
|
2025-05-05 20:43:28 +03:00
|
|
|
|
|
|
|
|
public void Log(LoggerCategory loggerCategory, string message)
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-08-07 22:34:25 +03:00
|
|
|
var output = DebugService.DoFileLog
|
2025-05-05 21:28:09 +03:00
|
|
|
? $"[{DateTime.Now.ToUniversalTime():yyyy-MM-dd HH:mm:ss}][{Enum.GetName(loggerCategory)}][{Category}]: {message}"
|
|
|
|
|
: message;
|
2025-08-07 22:34:25 +03:00
|
|
|
|
2025-05-05 20:43:28 +03:00
|
|
|
Console.WriteLine(output);
|
2024-12-22 16:38:47 +03:00
|
|
|
|
2025-08-07 22:34:25 +03:00
|
|
|
LogToFile(output);
|
2024-12-27 19:15:33 +03:00
|
|
|
}
|
|
|
|
|
|
2025-05-05 20:43:28 +03:00
|
|
|
public void Dispose()
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-05-05 21:28:09 +03:00
|
|
|
if (!DebugService.DoFileLog) return;
|
2025-08-07 22:34:25 +03:00
|
|
|
|
2025-05-05 20:43:28 +03:00
|
|
|
foreach (var (_, child) in Childs)
|
|
|
|
|
{
|
|
|
|
|
child.Dispose();
|
|
|
|
|
}
|
2025-08-07 22:34:25 +03:00
|
|
|
|
|
|
|
|
Childs.Clear(); // Not strictly necessary, but keeps intent clear
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ServiceLogger GetLogger(string category)
|
|
|
|
|
{
|
|
|
|
|
return Childs.GetOrAdd(category, key =>
|
|
|
|
|
{
|
|
|
|
|
var logger = new ServiceLogger(key, _directory)
|
|
|
|
|
{
|
|
|
|
|
Root = this
|
|
|
|
|
};
|
|
|
|
|
return logger;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void LogToFile(string output)
|
|
|
|
|
{
|
|
|
|
|
if (!DebugService.DoFileLog) return;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Root?.LogToFile(output); // Log to parent first
|
|
|
|
|
|
|
|
|
|
using var fileStream = File.Open(_path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
|
|
|
|
|
using var streamWriter = new StreamWriter(fileStream);
|
|
|
|
|
streamWriter.WriteLine(output);
|
|
|
|
|
}
|
|
|
|
|
catch (IOException ex)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"[Logging Error] Failed to write log: {ex.Message}");
|
|
|
|
|
}
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-05 20:43:28 +03:00
|
|
|
public static class LoggerExtensions
|
2024-12-22 16:38:47 +03:00
|
|
|
{
|
2025-08-07 22:34:25 +03:00
|
|
|
public static void Debug(this ILogger logger, string message)
|
2025-05-05 20:43:28 +03:00
|
|
|
{
|
|
|
|
|
logger.Log(LoggerCategory.Debug, message);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-07 22:34:25 +03:00
|
|
|
public static void Error(this ILogger logger, string message)
|
2025-05-05 20:43:28 +03:00
|
|
|
{
|
|
|
|
|
logger.Log(LoggerCategory.Error, message);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-07 22:34:25 +03:00
|
|
|
public static void Log(this ILogger logger, string message)
|
2025-05-05 20:43:28 +03:00
|
|
|
{
|
|
|
|
|
logger.Log(LoggerCategory.Log, message);
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-07 22:34:25 +03:00
|
|
|
public static void Error(this ILogger logger, Exception e)
|
2025-05-05 20:43:28 +03:00
|
|
|
{
|
2025-08-07 22:34:25 +03:00
|
|
|
Error(logger, e.Message + "\r\n" + e.StackTrace);
|
2025-05-05 20:43:28 +03:00
|
|
|
if (e.InnerException != null)
|
|
|
|
|
Error(logger, e.InnerException);
|
|
|
|
|
}
|
2024-12-22 16:38:47 +03:00
|
|
|
}
|