2024-06-26 14:45:54 -04:00
|
|
|
|
using System.Collections.Concurrent;
|
2024-06-19 21:11:42 -04:00
|
|
|
|
|
|
|
|
|
namespace ReCodeIt.Utils;
|
2024-06-11 19:18:48 -04:00
|
|
|
|
|
2024-06-13 18:15:52 -04:00
|
|
|
|
public static class Logger
|
2024-06-11 19:18:48 -04:00
|
|
|
|
{
|
2024-06-26 14:45:54 -04:00
|
|
|
|
// This queue will hold the messages to then place them on the wait list
|
|
|
|
|
private static readonly ConcurrentQueue<LogMessage> _messages = new();
|
|
|
|
|
private static bool Running = true;
|
|
|
|
|
private static bool IsTerminated;
|
|
|
|
|
// This dictionary acts as a waitlist, we are going to wait _defaultWaitTimeMs before logging all the messages
|
|
|
|
|
// coming from certain thread into the console, this way we can make sure they are grouped in relevance
|
|
|
|
|
private static readonly Dictionary<int, HeldMessages> _heldMessages = new();
|
|
|
|
|
// This is the timeout we will wait before logging a whole group of messages coming from a single thread
|
|
|
|
|
private static readonly TimeSpan _defaultWaitTimeMs = TimeSpan.FromMilliseconds(500);
|
|
|
|
|
|
2024-06-11 19:18:48 -04:00
|
|
|
|
static Logger()
|
|
|
|
|
{
|
|
|
|
|
if (File.Exists(_logPath))
|
|
|
|
|
{
|
|
|
|
|
File.Delete(_logPath);
|
|
|
|
|
File.Create(_logPath).Close();
|
|
|
|
|
}
|
2024-06-26 14:45:54 -04:00
|
|
|
|
|
|
|
|
|
Task.Factory.StartNew(LogThread, TaskCreationOptions.LongRunning);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void LogThread()
|
|
|
|
|
{
|
|
|
|
|
while (Running || _heldMessages.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
Thread.Sleep(TimeSpan.FromMilliseconds(100));
|
|
|
|
|
// Check the message queue and add them to the waitlist
|
|
|
|
|
CheckAndHoldMessages();
|
|
|
|
|
// Check the waitlist messages and see if any are ready to be logged
|
|
|
|
|
LogHeldMessages();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IsTerminated = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void LogHeldMessages()
|
|
|
|
|
{
|
|
|
|
|
var currentLogExecution = DateTime.Now;
|
|
|
|
|
foreach (var heldMessagesKP in _heldMessages)
|
|
|
|
|
{
|
|
|
|
|
var heldMessages = heldMessagesKP.Value;
|
|
|
|
|
if (currentLogExecution - heldMessages.FirstInsertion > _defaultWaitTimeMs)
|
|
|
|
|
{
|
|
|
|
|
while (heldMessages.Messages.TryDequeue(out var messageToLog))
|
|
|
|
|
LogInternal(messageToLog);
|
|
|
|
|
_heldMessages.Remove(heldMessagesKP.Key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void CheckAndHoldMessages()
|
|
|
|
|
{
|
|
|
|
|
var currentLogExecution = DateTime.Now;
|
|
|
|
|
while (_messages.TryDequeue(out var messageToHold))
|
|
|
|
|
{
|
|
|
|
|
if (!_heldMessages.TryGetValue(messageToHold.ThreadId, out var heldMessages))
|
|
|
|
|
{
|
|
|
|
|
heldMessages = new HeldMessages
|
|
|
|
|
{
|
|
|
|
|
FirstInsertion = currentLogExecution,
|
|
|
|
|
ThreadID = messageToHold.ThreadId
|
|
|
|
|
};
|
|
|
|
|
_heldMessages.Add(heldMessages.ThreadID, heldMessages);
|
|
|
|
|
}
|
|
|
|
|
heldMessages.Messages.Enqueue(messageToHold);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Terminate()
|
|
|
|
|
{
|
|
|
|
|
Running = false;
|
2024-06-11 19:18:48 -04:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-26 14:45:54 -04:00
|
|
|
|
public static bool IsRunning()
|
|
|
|
|
{
|
|
|
|
|
return !IsTerminated;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private const string _defaultFileName = "ReCodeIt.log";
|
2024-07-03 07:03:14 -04:00
|
|
|
|
private static string _logPath => Path.Combine(AppContext.BaseDirectory, "Data", "Settings.jsonc");
|
2024-06-13 07:45:40 -04:00
|
|
|
|
public static void ClearLog()
|
|
|
|
|
{
|
|
|
|
|
if (File.Exists(_logPath))
|
|
|
|
|
{
|
|
|
|
|
File.Delete(_logPath);
|
|
|
|
|
File.Create(_logPath).Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Log(object message, ConsoleColor color = ConsoleColor.Gray, bool silent = false)
|
2024-06-11 19:18:48 -04:00
|
|
|
|
{
|
2024-06-26 14:45:54 -04:00
|
|
|
|
_messages.Enqueue(new LogMessage {Message = message, Color = color, Silent = silent, ThreadId = Thread.CurrentThread.ManagedThreadId});
|
2024-06-12 18:59:08 -04:00
|
|
|
|
}
|
2024-06-26 14:45:54 -04:00
|
|
|
|
|
|
|
|
|
private static void LogInternal(LogMessage message)
|
2024-06-12 18:59:08 -04:00
|
|
|
|
{
|
2024-06-26 14:45:54 -04:00
|
|
|
|
if (!message.Silent)
|
2024-06-12 18:59:08 -04:00
|
|
|
|
{
|
2024-06-26 14:45:54 -04:00
|
|
|
|
Console.ForegroundColor = message.Color;
|
|
|
|
|
Console.WriteLine(message.Message);
|
2024-06-12 18:59:08 -04:00
|
|
|
|
Console.ResetColor();
|
|
|
|
|
}
|
2024-06-13 20:25:11 -04:00
|
|
|
|
|
2024-07-03 07:03:14 -04:00
|
|
|
|
//WriteToDisk(message.Message);
|
2024-06-12 18:59:08 -04:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-13 07:45:40 -04:00
|
|
|
|
private static void WriteToDisk(object message)
|
2024-06-12 18:59:08 -04:00
|
|
|
|
{
|
2024-06-11 19:18:48 -04:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
using (StreamWriter sw = File.AppendText(_logPath))
|
|
|
|
|
{
|
|
|
|
|
sw.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}");
|
2024-06-20 13:58:39 -04:00
|
|
|
|
sw.Close();
|
2024-06-11 19:18:48 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (IOException ex)
|
|
|
|
|
{
|
|
|
|
|
// Handle potential file writing errors gracefully
|
|
|
|
|
Console.WriteLine($"Error logging: {ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-26 14:45:54 -04:00
|
|
|
|
private class LogMessage
|
|
|
|
|
{
|
|
|
|
|
public object Message { get; init; }
|
|
|
|
|
public ConsoleColor Color { get; init; }
|
|
|
|
|
public bool Silent { get; init; }
|
|
|
|
|
public int ThreadId { get; init; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class HeldMessages
|
|
|
|
|
{
|
|
|
|
|
public int ThreadID { get; init; }
|
|
|
|
|
public DateTime FirstInsertion { get; init; }
|
|
|
|
|
public Queue<LogMessage> Messages { get; } = new(10);
|
|
|
|
|
}
|
2024-06-11 19:18:48 -04:00
|
|
|
|
}
|