Development Merge 2025.10.18 #4
							
								
								
									
										71
									
								
								Engine.Core/Debug/RotatingFileLogger.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								Engine.Core/Debug/RotatingFileLogger.cs
									
									
									
									
									
										Normal 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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user