diff --git a/Dalamud.Injector/EntryPoint.cs b/Dalamud.Injector/EntryPoint.cs index 3a21473c3..5501d073c 100644 --- a/Dalamud.Injector/EntryPoint.cs +++ b/Dalamud.Injector/EntryPoint.cs @@ -128,12 +128,58 @@ namespace Dalamud.Injector levelSwitch.MinimumLevel = LogEventLevel.Information; #endif + CullLogFile(logPath, 1 * 1024 * 1024); + Log.Logger = new LoggerConfiguration() .WriteTo.Async(a => a.File(logPath)) .MinimumLevel.ControlledBy(levelSwitch) .CreateLogger(); } + private static void CullLogFile(string logPath, int cullingFileSize) + { + try + { + var bufferSize = 4096; + + var logFile = new FileInfo(logPath); + + if (!logFile.Exists) + logFile.Create(); + + if (logFile.Length <= cullingFileSize) + return; + + var amountToCull = logFile.Length - cullingFileSize; + + if (amountToCull < bufferSize) + return; + + using var reader = new BinaryReader(logFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); + using var writer = new BinaryWriter(logFile.Open(FileMode.Open, FileAccess.Write, FileShare.ReadWrite)); + + reader.BaseStream.Seek(amountToCull, SeekOrigin.Begin); + + var read = -1; + var total = 0; + var buffer = new byte[bufferSize]; + while (read != 0) + { + read = reader.Read(buffer, 0, buffer.Length); + writer.Write(buffer, 0, read); + total += read; + } + + writer.BaseStream.SetLength(total); + } + catch (Exception ex) + { + var caption = "XIVLauncher Error"; + var message = $"Log cull threw an exception: {ex.Message}\n{ex.StackTrace ?? string.Empty}"; + _ = MessageBoxW(IntPtr.Zero, message, caption, MessageBoxType.IconError | MessageBoxType.Ok); + } + } + private static Process GetProcess(string arg) { Process process; diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs index a04477647..378f841fd 100644 --- a/Dalamud/EntryPoint.cs +++ b/Dalamud/EntryPoint.cs @@ -12,6 +12,8 @@ using Serilog; using Serilog.Core; using Serilog.Events; +using static Dalamud.NativeFunctions; + namespace Dalamud { /// @@ -43,11 +45,16 @@ namespace Dalamud /// The containing information needed to initialize Dalamud. private static void RunThread(DalamudStartInfo info) { + // Setup logger + var levelSwitch = InitLogging(info.WorkingDirectory); + // Load configuration first to get some early persistent state, like log level var configuration = DalamudConfiguration.Load(info.ConfigurationPath); - // Setup logger - var levelSwitch = InitLogging(info.WorkingDirectory, configuration); + // Set the appropriate logging level from the configuration +#if !DEBUG + levelSwitch.MinimumLevel = configuration.LogLevel; +#endif // Log any unhandled exception. AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; @@ -88,30 +95,96 @@ namespace Dalamud } } - private static LoggingLevelSwitch InitLogging(string baseDirectory, DalamudConfiguration configuration) + private static LoggingLevelSwitch InitLogging(string baseDirectory) { #if DEBUG var logPath = Path.Combine(baseDirectory, "dalamud.log"); + var oldPath = Path.Combine(baseDirectory, "dalamud.log.old"); #else var logPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log"); + var oldPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log.old"); #endif - var levelSwitch = new LoggingLevelSwitch(); + CullLogFile(logPath, oldPath, 1 * 1024 * 1024); + CullLogFile(oldPath, null, 10 * 1024 * 1024); -#if DEBUG - levelSwitch.MinimumLevel = LogEventLevel.Verbose; -#else - levelSwitch.MinimumLevel = configuration.LogLevel; -#endif + var levelSwitch = new LoggingLevelSwitch(LogEventLevel.Verbose); Log.Logger = new LoggerConfiguration() - .WriteTo.Async(a => a.File(logPath, fileSizeLimitBytes: 5 * 1024 * 1024, rollOnFileSizeLimit: true)) - .WriteTo.Sink(SerilogEventSink.Instance) - .MinimumLevel.ControlledBy(levelSwitch) - .CreateLogger(); + .WriteTo.Async(a => a.File(logPath)) + .WriteTo.Sink(SerilogEventSink.Instance) + .MinimumLevel.ControlledBy(levelSwitch) + .CreateLogger(); return levelSwitch; } + private static void CullLogFile(string logPath, string? oldPath, int cullingFileSize) + { + try + { + var bufferSize = 4096; + + var logFile = new FileInfo(logPath); + + if (!logFile.Exists) + logFile.Create(); + + if (logFile.Length <= cullingFileSize) + return; + + var amountToCull = logFile.Length - cullingFileSize; + + if (amountToCull < bufferSize) + return; + + if (oldPath != null) + { + var oldFile = new FileInfo(oldPath); + + if (!oldFile.Exists) + oldFile.Create(); + + using var reader = new BinaryReader(logFile.Open(FileMode.Open, FileAccess.Read)); + using var writer = new BinaryWriter(oldFile.Open(FileMode.Append, FileAccess.Write)); + + var read = -1; + var total = 0; + var buffer = new byte[bufferSize]; + while (read != 0 && total < amountToCull) + { + read = reader.Read(buffer, 0, buffer.Length); + writer.Write(buffer, 0, read); + total += read; + } + } + + { + using var reader = new BinaryReader(logFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); + using var writer = new BinaryWriter(logFile.Open(FileMode.Open, FileAccess.Write, FileShare.ReadWrite)); + + reader.BaseStream.Seek(amountToCull, SeekOrigin.Begin); + + var read = -1; + var total = 0; + var buffer = new byte[bufferSize]; + while (read != 0) + { + read = reader.Read(buffer, 0, buffer.Length); + writer.Write(buffer, 0, read); + total += read; + } + + writer.BaseStream.SetLength(total); + } + } + catch (Exception ex) + { + var caption = "XIVLauncher Error"; + var message = $"Log cull threw an exception: {ex.Message}\n{ex.StackTrace ?? string.Empty}"; + _ = MessageBoxW(IntPtr.Zero, message, caption, MessageBoxType.IconError | MessageBoxType.Ok); + } + } + private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs args) { switch (args.ExceptionObject)