/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: DirLogArchive.cpp Date: 2022-2-6 Author: Reece ***/ #include #include "DirLogArchive.hpp" #include "FileSink.hpp" namespace Aurora::Logging::Sinks { static void CleanupOldLogs(DirectoryLogger logger, const AuString &baseLogPath) { AuList files; AuList> fileMeta; AuUInt64 qwSize {}; auto doScan = [&]() { files.clear(); fileMeta.clear(); qwSize = 0; AuIOFS::FilesInDirectory(baseLogPath, files); for (const auto &file : files) { AuIOFS::Stat stat; AuIOFS::StatFile(baseLogPath + "/" + file, stat); fileMeta.push_back(AuMakePair(file, stat)); qwSize += stat.uSize; } std::sort(fileMeta.begin(), fileMeta.end(), [](AuPair a, AuPair b) { return AuGet<1>(a).modified < AuGet<1>(b).modified; }); }; doScan(); if (logger.uMaxLogsOrZeroBeforeCompress) { if (fileMeta.size() > logger.uMaxLogsOrZeroBeforeCompress) { for (AuUInt i = logger.uMaxLogsOrZeroBeforeCompress; i < fileMeta.size(); i++) { auto path = baseLogPath + "/" + fileMeta[i].first; if (AuEndsWith(path, ".zst")) continue; if (AuIOFS::Compress(path)) { AuIOFS::Remove(path); } } doScan(); } } if (logger.uMaxFileTimeInDeltaMSOrZeroBeforeCompress) { auto qwMaxTime = AuTime::CurrentClockMS() - logger.uMaxFileTimeInDeltaMSOrZeroBeforeCompress; bool bRescan {}; for (AuUInt i = 0; i < fileMeta.size(); i++) { if (qwMaxTime > fileMeta[i].second.modified) { auto path = baseLogPath + "/" + fileMeta[i].first; if (AuEndsWith(path, ".zst")) continue; if (AuIOFS::Compress(path)) { AuIOFS::Remove(path); } bRescan = true; } } if (bRescan) { doScan(); } } if (logger.uMaxCumulativeFileSizeInMiBOrZeroBeforeCompress) { bool bRescan {}; if (qwSize > logger.uMaxCumulativeFileSizeInMiBOrZeroBeforeCompress) { std::sort(fileMeta.begin(), fileMeta.end(), [](AuPair a, AuPair b) { return AuGet<1>(a).uSize > AuGet<1>(b).uSize; }); for (AuUInt i = 0; i < fileMeta.size(); i++) { if (qwSize <= logger.uMaxCumulativeFileSizeInMiBOrZeroBeforeCompress) { break; } auto path = baseLogPath + "/" + fileMeta[i].first; if (AuEndsWith(path, ".zst")) continue; if (AuIOFS::Compress(path)) { AuIOFS::Remove(path); } bRescan = true; } } if (bRescan) { doScan(); } } if (logger.uMaxLogsOrZeroBeforeDelete) { if (fileMeta.size() > logger.uMaxLogsOrZeroBeforeDelete) { for (AuUInt i = logger.uMaxLogsOrZeroBeforeDelete; i < fileMeta.size(); i++) { AuIOFS::Remove(baseLogPath + "/" + fileMeta[i].first); } doScan(); } } if (logger.uMaxCumulativeFileSizeInMiBOrZeroBeforeDelete) { bool bRescan {}; if (qwSize > logger.uMaxCumulativeFileSizeInMiBOrZeroBeforeDelete) { std::sort(fileMeta.begin(), fileMeta.end(), [](AuPair a, AuPair b) { return AuGet<1>(a).uSize > AuGet<1>(b).uSize; }); for (AuUInt i = 0; i < fileMeta.size(); i++) { if (qwSize <= logger.uMaxCumulativeFileSizeInMiBOrZeroBeforeDelete) { break; } if (AuIOFS::Remove(baseLogPath + "/" + fileMeta[i].first)) { qwSize -= fileMeta[i].second.uSize; bRescan = true; } } } if (bRescan) { doScan(); } } if (logger.uMaxFileTimeInDeltaMSOrZeroBeforeDelete) { auto qwMaxTime = AuTime::CurrentClockMS() - logger.uMaxFileTimeInDeltaMSOrZeroBeforeDelete; for (AuUInt i = 0; i < fileMeta.size(); i++) { if (qwMaxTime > fileMeta[i].second.modified) { AuIOFS::Remove(baseLogPath + "/" + fileMeta[i].first); } } } } IBasicSink *NewDirectoryLoggerNew(const AuString &baseDirectory, DirectoryLogger meta, bool bBinary) { AuString path; auto tm = Time::ToCivilTime(Time::CurrentClockMS()); path = fmt::format("{}/{:04}-{:02}-{:02}T{:02}-{:02}-{:02}Z.{}", baseDirectory, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, bBinary ? ".log" : ".txt"); CleanupOldLogs(meta, baseDirectory); return Sinks::NewFileSinkNew(path, bBinary); } void NewDirectoryLoggerRelease(IBasicSink *pLogger) { Sinks::NewFileSinkRelease(AuStaticCast(pLogger)); } }