using System; using System.Collections.Concurrent; using System.IO; using System.Linq; namespace StardewModdingAPI.Framework { /// A log writer which queues messages for output, and periodically flushes them to the console and log file. internal class LogWriter { /********* ** Properties *********/ /// The singleton instance. private static LogWriter _instance; /// The queued messages to flush. private static ConcurrentQueue Queue; /// The underlying file stream. private static StreamWriter FileStream; /********* ** Accessors *********/ /// The singleton instance. internal static LogWriter Instance { get { if (LogWriter._instance == null) { LogWriter._instance = new LogWriter(); // Field cannot be used by anything else regardless, do not surround with lock { } // ReSharper disable once InconsistentlySynchronizedField LogWriter.Queue = new ConcurrentQueue(); Console.WriteLine(Constants.LogPath); // If the ErrorLogs dir doesn't exist StreamWriter will throw an exception. if (!Directory.Exists(Constants.LogDir)) { Directory.CreateDirectory(Constants.LogDir); } LogWriter.FileStream = new StreamWriter(Constants.LogPath, false); Console.WriteLine("Created log instance"); } return LogWriter._instance; } } /********* ** Public methods *********/ /// Queue a message for output. /// The message to log. public void WriteToLog(string message) { lock (LogWriter.Queue) { var logEntry = new LogInfo(message); LogWriter.Queue.Enqueue(logEntry); if (LogWriter.Queue.Any()) this.FlushLog(); } } /// Queue a message for output. /// The message to log. public void WriteToLog(LogInfo message) { lock (LogWriter.Queue) { LogWriter.Queue.Enqueue(message); if (LogWriter.Queue.Any()) this.FlushLog(); } } /********* ** Private methods *********/ /// Construct an instance. private LogWriter() { } /// Flush the underlying queue to the console and file. private void FlushLog() { lock (LogWriter.FileStream) { LogInfo entry; while (LogWriter.Queue.TryDequeue(out entry)) { string m = $"[{entry.LogTime}] {entry.Message}"; Console.ForegroundColor = entry.Colour; Console.WriteLine(m); Console.ForegroundColor = ConsoleColor.Gray; LogWriter.FileStream.WriteLine(m); } LogWriter.FileStream.Flush(); } } } }