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);
 | 
						|
}
 |