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();
}
}
}
}