feat: rotating file logger added

This commit is contained in:
Syntriax 2025-08-08 16:28:08 +03:00
parent 3912706d27
commit efed24de20

View File

@ -0,0 +1,71 @@
using System;
using System.IO;
using System.Linq;
namespace Engine.Core.Debug;
public class RotatingFileLogger : ILogger
{
public readonly FileLogger FileLogger = null!;
public readonly string Directory = string.Empty;
public readonly int RotateLength = 3;
public RotatingFileLogger(string directory, string namePrefix, string nameSuffix = "", int rotateLength = 3)
{
RotateLength = rotateLength;
string fileName = Path.Combine(directory, namePrefix);
if (!string.IsNullOrWhiteSpace(nameSuffix))
fileName += $"_{nameSuffix}";
bool isRelativePath = Path.GetFullPath(fileName).CompareTo(fileName) != 0;
if (isRelativePath)
fileName = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName));
if (File.Exists($"{fileName}.log"))
RenameExistingLogs(fileName, RotateLength);
FileLogger = new(fileName);
Directory = Path.GetDirectoryName(fileName) ?? throw new("Unexpected error on getting directory of logger path");
RotateLastLogs(Directory, namePrefix, RotateLength);
}
private static void RenameExistingLogs(string filePath, int rotateLength)
{
for (int i = rotateLength - 1; i >= 0; i--)
{
string source = i == 0
? $"{filePath}.log"
: $"{filePath}_{i}.log";
string dest = $"{filePath}_{i + 1}.log";
if (!File.Exists(source))
continue;
if (File.Exists(dest))
File.Delete(dest);
File.Move(source, dest);
}
}
private static void RotateLastLogs(string directory, string prefix, int rotateLength)
{
IOrderedEnumerable<string> logs = System.IO.Directory.GetFiles(directory, $"{prefix}*.log")
.OrderBy(File.GetCreationTime);
foreach (string file in logs.Skip(rotateLength))
try
{
ILogger.Shared.Log($"Removing log file located at \"{file}\" during rotation.");
File.Delete(file);
}
catch (Exception e) { ILogger.Shared.LogException($"Failed to rotate log file at \"{file}\"", e); }
}
public ILogger.Level FilterLevel { get => FileLogger.FilterLevel; set => FileLogger.FilterLevel = value; }
public void Log(string message, ILogger.Level level = ILogger.Level.Info, bool force = false) => FileLogger.Log(message, level, force);
}