/*** 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 = [&](bool bOrder) { 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) { if (bOrder) { return AuGet<1>(a).modifiedNs < AuGet<1>(b).modifiedNs; } else { return AuGet<1>(a).modifiedNs > AuGet<1>(b).modifiedNs; } }); }; if (logger.uMaxLogsOrZeroBeforeCompress) { doScan(false); 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); } } } } if (logger.uMaxFileTimeInDeltaMSOrZeroBeforeCompress) { doScan(true); auto qwMaxTime = AuTime::CurrentClockMS() - logger.uMaxFileTimeInDeltaMSOrZeroBeforeCompress; for (AuUInt i = 0; i < fileMeta.size(); i++) { if (qwMaxTime > AuNSToMS(fileMeta[i].second.modifiedNs)) { auto path = baseLogPath + "/" + fileMeta[i].first; if (AuEndsWith(path, ".zst")) continue; if (AuIOFS::Compress(path)) { AuIOFS::Remove(path); } } } } if (logger.uMaxCumulativeFileSizeInMiBOrZeroBeforeCompress) { doScan(false); 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); } } } } if (logger.uMaxLogsOrZeroBeforeDelete) { doScan(false); if (fileMeta.size() > logger.uMaxLogsOrZeroBeforeDelete) { for (AuUInt i = logger.uMaxLogsOrZeroBeforeDelete; i < fileMeta.size(); i++) { AuIOFS::Remove(baseLogPath + "/" + fileMeta[i].first); } } } if (logger.uMaxCumulativeFileSizeInMiBOrZeroBeforeDelete) { doScan(false); 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; } } } } if (logger.uMaxFileTimeInDeltaMSOrZeroBeforeDelete) { doScan(true); auto qwMaxTime = AuTime::CurrentClockMS() - logger.uMaxFileTimeInDeltaMSOrZeroBeforeDelete; for (AuUInt i = 0; i < fileMeta.size(); i++) { if (qwMaxTime > AuNSToMS(fileMeta[i].second.modifiedNs)) { 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.year, tm.mon + 1, tm.mday + 1, tm.hour, tm.min, tm.sec, bBinary ? "log" : "txt"); CleanupOldLogs(meta, baseDirectory); return Sinks::NewFileSinkNew(path, bBinary); } void NewDirectoryLoggerRelease(IBasicSink *pLogger) { Sinks::NewFileSinkRelease(AuStaticCast(pLogger)); } }