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. /// Only one instance should be created. internal class LogWriter { /********* ** Properties *********/ /// The queued messages to flush. private readonly ConcurrentQueue Queue; /// The underlying file stream. private readonly StreamWriter FileStream; /********* ** Public methods *********/ /// Construct an instance. /// The log path to write. public LogWriter(string path) { // create log directory (required for stream writer) Directory.CreateDirectory(Path.GetDirectoryName(path)); // initialise this.Queue = new ConcurrentQueue(); this.FileStream = new StreamWriter(Constants.LogPath, false); } /// Queue a message for output. /// The message to log. public void WriteToLog(string message) { lock (this.Queue) { var logEntry = new LogInfo(message); this.Queue.Enqueue(logEntry); if (this.Queue.Any()) this.FlushLog(); } } /// Queue a message for output. /// The message to log. public void WriteToLog(LogInfo message) { lock (this.Queue) { this.Queue.Enqueue(message); if (this.Queue.Any()) this.FlushLog(); } } /********* ** Private methods *********/ /// Flush the underlying queue to the console and file. private void FlushLog() { lock (this.FileStream) { LogInfo entry; while (this.Queue.TryDequeue(out entry)) { string message = $"[{entry.LogTime}] {entry.Message}"; Console.ForegroundColor = entry.Colour; Console.WriteLine(message); Console.ForegroundColor = ConsoleColor.Gray; this.FileStream.WriteLine(message); } this.FileStream.Flush(); } } } }