72 lines
2.4 KiB
C#
72 lines
2.4 KiB
C#
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);
|
|
}
|