using System;
using System.Collections.Generic;
using System.Linq;
namespace TINK.Model.Logging
{
public class LoggingDirectoryManager : ILoggingDirectoryManager
{
/// Name of logging subdirectory.
private const string LOGDIRECTORYTITLE = "Log";
/// Prevents an invalid instance to be created.
private LoggingDirectoryManager() { }
public LoggingDirectoryManager(
Func> p_oFileListProvider,
Func p_oDirectoryExistsChecker,
Action p_oDirectoryCreator,
Action p_oFileEraser,
string p_oLogFilePath,
char p_strDirectorySeparatorChar,
int p_iRetainedFilesCountLimit)
{
m_oFileListProvider = p_oFileListProvider ?? throw new ArgumentException($"Can not instantiate {nameof(LoggingDirectoryManager)}- object. File list provider delegate can not be null.");
if (p_oDirectoryExistsChecker == null)
{
throw new ArgumentException($"Can not instantiate {nameof(LoggingDirectoryManager)}- object. Directory existance checker delegate can not be null.");
}
if (p_oDirectoryCreator == null)
{
throw new ArgumentException($"Can not instantiate {nameof(LoggingDirectoryManager)}- object. Directory creator delegate can not be null.");
}
m_oFileEraser = p_oFileEraser ?? throw new ArgumentException($"Can not instantiate {nameof(LoggingDirectoryManager)}- object. File eraser delegate can not be null.");
if (string.IsNullOrEmpty(p_oLogFilePath))
{
throw new ArgumentException($"Can not instantiate {nameof(LoggingDirectoryManager)}- object. Log file path can not be null or empty.");
}
if (string.IsNullOrEmpty(p_strDirectorySeparatorChar.ToString()))
{
throw new ArgumentException($"Can not instantiate {nameof(LoggingDirectoryManager)}- object. Directory separtor character can not be null or empty.");
}
if (p_iRetainedFilesCountLimit < 1)
{
throw new ArgumentException($"Can not instantiate {nameof(LoggingDirectoryManager)}- object. Count of retained log files is {p_iRetainedFilesCountLimit} but must be equal or larger one.");
}
DirectorySeparatorChar = p_strDirectorySeparatorChar.ToString();
LogFilePath = $"{p_oLogFilePath}{DirectorySeparatorChar}{LOGDIRECTORYTITLE}";
m_iRetainedFilesCountLimit = p_iRetainedFilesCountLimit;
if (string.IsNullOrEmpty(LogFileTitle))
{
LogFileTitle = $"{ DateTime.Now:yyyy_MM_dd_HH_mm_ss}.jsnl";
}
// Create directory if direcotry does not exist.
if (p_oDirectoryExistsChecker(LogFilePath) == false)
{
try
{
p_oDirectoryCreator(LogFilePath);
}
catch (Exception l_oException)
{
throw new FileOperationException($"Logging directory {LogFilePath} could not be created successfully.", l_oException);
}
}
}
/// Deletes files which are out of retainment scope.
public void DeleteObsoleteLogs()
{
var l_oExceptions = new List();
var l_oSortedFileArray = m_oFileListProvider(LogFilePath).OrderByDescending(x => x).ToArray();
for (int l_iIndex = l_oSortedFileArray.Length - 1;
l_iIndex >= m_iRetainedFilesCountLimit - 1; /* files remaining count must be m_iRetainedFilesCountLimit - 1 because new log file will be added afterwards */
l_iIndex --)
{
try
{
m_oFileEraser(l_oSortedFileArray[l_iIndex]);
}
catch (Exception l_oExpetion)
{
// Getting list of log files found.
l_oExceptions.Add(l_oExpetion);
}
}
if (l_oExceptions.Count <= 0)
{
return;
}
throw new AggregateException("Deleting obsolete log files failed.", l_oExceptions.ToArray());
}
/// Gets all log files in logging directory.
///
/// List of log files.
public IList GetLogFiles()
{
try
{
return m_oFileListProvider(LogFilePath).OrderBy(x => x).ToList();
}
catch (Exception l_oExpetion)
{
// Getting list of log files found.
throw new FileOperationException("Getting list of log files failed.", l_oExpetion);
}
}
/// Holds delegate to provide file names.
private readonly Func> m_oFileListProvider;
/// Holds delegate to delete files.
private readonly Action m_oFileEraser;
/// Holds delegate to provide file names.
private int m_iRetainedFilesCountLimit;
/// Holds the log file name.
private string LogFileTitle { get; }
/// Holds the log file name.
public string LogFilePath { get; }
/// Holds the directory separator character.
private string DirectorySeparatorChar { get; }
/// Holds the log file name.
public string LogFileName { get { return $"{LogFilePath}{DirectorySeparatorChar}{LogFileTitle}"; } }
}
}