Implement manual log file rotating and culling

This commit is contained in:
Raymond 2021-08-09 10:04:05 -04:00
parent f66e5ca08b
commit 61b5b2631f
2 changed files with 132 additions and 13 deletions

View file

@ -128,12 +128,58 @@ namespace Dalamud.Injector
levelSwitch.MinimumLevel = LogEventLevel.Information; levelSwitch.MinimumLevel = LogEventLevel.Information;
#endif #endif
CullLogFile(logPath, 1 * 1024 * 1024);
Log.Logger = new LoggerConfiguration() Log.Logger = new LoggerConfiguration()
.WriteTo.Async(a => a.File(logPath)) .WriteTo.Async(a => a.File(logPath))
.MinimumLevel.ControlledBy(levelSwitch) .MinimumLevel.ControlledBy(levelSwitch)
.CreateLogger(); .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) private static Process GetProcess(string arg)
{ {
Process process; Process process;

View file

@ -12,6 +12,8 @@ using Serilog;
using Serilog.Core; using Serilog.Core;
using Serilog.Events; using Serilog.Events;
using static Dalamud.NativeFunctions;
namespace Dalamud namespace Dalamud
{ {
/// <summary> /// <summary>
@ -43,11 +45,16 @@ namespace Dalamud
/// <param name="info">The <see cref="DalamudStartInfo"/> containing information needed to initialize Dalamud.</param> /// <param name="info">The <see cref="DalamudStartInfo"/> containing information needed to initialize Dalamud.</param>
private static void RunThread(DalamudStartInfo info) 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 // Load configuration first to get some early persistent state, like log level
var configuration = DalamudConfiguration.Load(info.ConfigurationPath); var configuration = DalamudConfiguration.Load(info.ConfigurationPath);
// Setup logger // Set the appropriate logging level from the configuration
var levelSwitch = InitLogging(info.WorkingDirectory, configuration); #if !DEBUG
levelSwitch.MinimumLevel = configuration.LogLevel;
#endif
// Log any unhandled exception. // Log any unhandled exception.
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
@ -88,23 +95,22 @@ namespace Dalamud
} }
} }
private static LoggingLevelSwitch InitLogging(string baseDirectory, DalamudConfiguration configuration) private static LoggingLevelSwitch InitLogging(string baseDirectory)
{ {
#if DEBUG #if DEBUG
var logPath = Path.Combine(baseDirectory, "dalamud.log"); var logPath = Path.Combine(baseDirectory, "dalamud.log");
var oldPath = Path.Combine(baseDirectory, "dalamud.log.old");
#else #else
var logPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log"); var logPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log");
var oldPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log.old");
#endif #endif
var levelSwitch = new LoggingLevelSwitch(); CullLogFile(logPath, oldPath, 1 * 1024 * 1024);
CullLogFile(oldPath, null, 10 * 1024 * 1024);
#if DEBUG var levelSwitch = new LoggingLevelSwitch(LogEventLevel.Verbose);
levelSwitch.MinimumLevel = LogEventLevel.Verbose;
#else
levelSwitch.MinimumLevel = configuration.LogLevel;
#endif
Log.Logger = new LoggerConfiguration() Log.Logger = new LoggerConfiguration()
.WriteTo.Async(a => a.File(logPath, fileSizeLimitBytes: 5 * 1024 * 1024, rollOnFileSizeLimit: true)) .WriteTo.Async(a => a.File(logPath))
.WriteTo.Sink(SerilogEventSink.Instance) .WriteTo.Sink(SerilogEventSink.Instance)
.MinimumLevel.ControlledBy(levelSwitch) .MinimumLevel.ControlledBy(levelSwitch)
.CreateLogger(); .CreateLogger();
@ -112,6 +118,73 @@ namespace Dalamud
return levelSwitch; 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) private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs args)
{ {
switch (args.ExceptionObject) switch (args.ExceptionObject)