diff --git a/Knossos.NET/Classes/Knossos.cs b/Knossos.NET/Classes/Knossos.cs index 47e0b7df..f0910cb2 100644 --- a/Knossos.NET/Classes/Knossos.cs +++ b/Knossos.NET/Classes/Knossos.cs @@ -70,7 +70,7 @@ static Knossos() catch (Exception ex) { //At this stage we can only log to console - Log.WriteToConsole("Knossos() - " + ex.Message); + _ = Log.WriteToConsole("Knossos() - " + ex.Message); } //Important!!! The first time it needs to be ran after checking if we are in portable mode or not //Due to the Knossos data folder path changing diff --git a/Knossos.NET/Models/Log.cs b/Knossos.NET/Models/Log.cs index 26ce3725..9c26a739 100644 --- a/Knossos.NET/Models/Log.cs +++ b/Knossos.NET/Models/Log.cs @@ -1,9 +1,8 @@ using Avalonia.Threading; using System; -using System.Collections.Generic; +using System.Collections.Concurrent; using System.Diagnostics; using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; @@ -23,63 +22,79 @@ public enum LogSeverity private class LogEntry { - string logString = string.Empty; - bool writeToFile = false; + public string LogString { get; } + public bool WriteToFile { get; } public LogEntry(LogSeverity logSeverity, string from, string data) { - logString = DateTime.Now.ToString() + " - *" + logSeverity.ToString() + "* : (" + from + ") " + data; - if (Knossos.globalSettings.enableLogFile && (int)logSeverity >= Knossos.globalSettings.logLevel) - { - writeToFile = true; - } - Task.Factory.StartNew(() => { - ProcessLogEntry(); - }); + LogString = $"{DateTime.Now} - *{logSeverity}* : ({from}) {data}"; + + WriteToFile = Knossos.globalSettings.enableLogFile && (int)logSeverity >= Knossos.globalSettings.logLevel; + } + } + + public static readonly string LogFilePath = Path.Combine(KnUtils.GetKnossosDataFolderPath(), "Knossos.log"); + private static readonly ConcurrentQueue queuedLogs = new(); + private static readonly Task _consumerTask; + private static readonly int maxFileWriteAttempts = 5; + + static Log() + { + _consumerTask = Task.Run(ConsumeQueueAsync); + if(Knossos.globalSettings.enableLogFile) + { + _ = WriteToFileAsync($"{DateTime.Now.ToString()} Init logger..."); } + } - private async void ProcessLogEntry() + private static async Task ConsumeQueueAsync() + { + while (true) { - while (!queuedLogs.Any() || queuedLogs.Peek() != this) + if (queuedLogs.TryDequeue(out var entry)) + { + await ProcessEntryAsync(entry); + } + else + { await Task.Delay(10); - WriteToConsole(); - if (writeToFile) - WriteToFile(); - queuedLogs.Dequeue(); + } } + } - private void WriteToConsole() + private static async Task ProcessEntryAsync(LogEntry entry) + { + // Siempre se escribe en consola (UI thread) + await WriteToConsole(entry.LogString); + + // Si corresponde, escribir en archivo + if (entry.WriteToFile) { - Log.WriteToConsole(logString); + await WriteToFileAsync(entry.LogString); } + } - private void WriteToFile(int attempt = 1) + private static async Task WriteToFileAsync(string data, int attempt = 1) + { + try + { + await using var writer = new StreamWriter(LogFilePath, true, Encoding.UTF8); + await writer.WriteLineAsync(data); + } + catch (Exception ex) { - try + if (attempt < maxFileWriteAttempts) { - using (var writer = new StreamWriter(LogFilePath, true)) - { - writer.WriteLine(logString, Encoding.UTF8); - } - }catch(Exception ex) + await Task.Delay(50 * attempt); + await WriteToFileAsync(data, attempt + 1); + } + else { - if(attempt < maxFileWriteAttempts) - { - attempt++; - WriteToFile(attempt); - } - else - { - Log.WriteToConsole("Failed to write to the logfile, reason: " + ex.ToString() + " \nFilePath:"+ LogFilePath); - } + await WriteToConsole($"Failed to write to logfile: {ex.Message}\nFilePath: {LogFilePath}"); } } } - public static readonly string LogFilePath = KnUtils.GetKnossosDataFolderPath() + Path.DirectorySeparatorChar + "Knossos.log"; - private static readonly int maxFileWriteAttempts = 5; - private static Queue queuedLogs = new Queue(); - /// /// Write a log entry to console and file /// It is always written to console, and it is written to file ONLY if the logseverity @@ -114,7 +129,7 @@ public static void Add(LogSeverity logSeverity, string from, Exception exception /// Write a string to VS console and the UI console on the Debug tab /// /// - public async static void WriteToConsole(string data) + public static async Task WriteToConsole(string data) { try { diff --git a/Knossos.NET/Models/Nebula.cs b/Knossos.NET/Models/Nebula.cs index accd5dbf..7d2042d7 100644 --- a/Knossos.NET/Models/Nebula.cs +++ b/Knossos.NET/Models/Nebula.cs @@ -651,7 +651,7 @@ private static async Task WaitForFileAccess(string filename) } catch (IOException) { - Log.WriteToConsole("repo_minimal.json is in use. Waiting for file access..."); + _ = Log.WriteToConsole("repo_minimal.json is in use. Waiting for file access..."); await Task.Delay(500); if (cancellationToken != null && cancellationToken!.IsCancellationRequested) {