using System.IO;
using System.Text;
using System.Threading;
namespace BepInEx.Logging
{
///
/// Logs entries using Unity specific outputs.
///
public class DiskLogListener : ILogListener
{
///
/// Log levels to display.
///
public LogLevel DisplayedLogLevel { get; set; }
///
/// Writer for the disk log.
///
public TextWriter LogWriter { get; protected set; }
///
/// Timer for flushing the logs to a file.
///
public Timer FlushTimer { get; protected set; }
///
/// Whether to write Unity log messages to disk log.
///
public bool WriteFromUnityLog { get; set; }
///
/// Creates a new disk log listener.
///
/// Path to the log.
/// Log levels to display.
/// Whether to append logs to an already existing log file.
/// Whether to include Unity log into the disk log.
public DiskLogListener(string localPath, LogLevel displayedLogLevel = LogLevel.Info, bool appendLog = false, bool includeUnityLog = false)
{
WriteFromUnityLog = includeUnityLog;
DisplayedLogLevel = displayedLogLevel;
int counter = 1;
FileStream fileStream;
while (!Utility.TryOpenFileStream(Path.Combine(Paths.BepInExRootPath, localPath), appendLog ? FileMode.Append : FileMode.Create, out fileStream, share: FileShare.Read, access: FileAccess.Write))
{
if (counter == 5)
{
Logger.LogError("Couldn't open a log file for writing. Skipping log file creation");
return;
}
Logger.LogWarning($"Couldn't open log file '{localPath}' for writing, trying another...");
localPath = $"LogOutput.log.{counter++}";
}
LogWriter = TextWriter.Synchronized(new StreamWriter(fileStream, Encoding.UTF8));
FlushTimer = new Timer(o => { LogWriter?.Flush(); }, null, 2000, 2000);
}
///
public void LogEvent(object sender, LogEventArgs eventArgs)
{
if (!WriteFromUnityLog && eventArgs.Source is UnityLogSource)
return;
if ((eventArgs.Level & DisplayedLogLevel) == 0)
return;
LogWriter.WriteLine(eventArgs.ToString());
}
///
public void Dispose()
{
FlushTimer?.Dispose();
LogWriter?.Flush();
LogWriter?.Dispose();
}
///
/// Disposes of Disk logger
///
~DiskLogListener()
{
Dispose();
}
}
}