From bb054b39e41675e8c065bc84c75f60755e4d8268 Mon Sep 17 00:00:00 2001 From: Etienne Dechamps Date: Thu, 5 May 2022 21:04:12 +0100 Subject: [PATCH] Cap logfile size See dechamps/FlexASIO#146 --- log.cpp | 30 ++++++++++++++++++++++++++++-- log.h | 14 ++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/log.cpp b/log.cpp index 629c071..71786a7 100644 --- a/log.cpp +++ b/log.cpp @@ -107,14 +107,40 @@ namespace dechamps_cpplog { Logger(this) << "Host process: " << GetModuleName(); } - FileLogSink::FileLogSink(const std::filesystem::path& path) : stream(path, std::ios::app | std::ios::out) { - Logger(this) << "Logfile opened: " << path; + FileLogSink::FileLogSink(std::filesystem::path path, Options options) : path(std::move(path)), options(std::move(options)), stream(this->path, std::ios::app | std::ios::out) { + Logger(this) << "Logfile opened: " << this->path; + CheckSize(); } FileLogSink::~FileLogSink() { Logger(this) << "Closing logfile"; } + void FileLogSink::Write(const std::string_view str) { + if (!stream.is_open()) return; + + stream_sink.Write(str); + + const auto size = str.size(); + if (size >= bytesRemainingUntilSizeCheck) CheckSize(); + else bytesRemainingUntilSizeCheck -= size; + } + + void FileLogSink::CheckSize() { + bytesRemainingUntilSizeCheck = (std::numeric_limits::max)(); + + const auto sizeBytes = std::filesystem::file_size(path); + const auto maxSizeBytes = options.maxSizeBytes; + Logger(this) << "Current log file size is " << sizeBytes << " bytes (maximum allowed: " << maxSizeBytes << " bytes)"; + + if (sizeBytes < maxSizeBytes) { + bytesRemainingUntilSizeCheck = options.sizeCheckPeriodBytes; + return; + } + Logger(this) << "Closing logfile as the maximum size is exceeded"; + stream.close(); + } + void ThreadSafeLogSink::Write(const std::string_view str) { std::scoped_lock lock(mutex); backend.Write(str); diff --git a/log.h b/log.h index c43bd6a..3d4fa7b 100644 --- a/log.h +++ b/log.h @@ -38,14 +38,24 @@ namespace dechamps_cpplog { class FileLogSink final : public LogSink { public: - FileLogSink(const std::filesystem::path& path); + struct Options final { + uintmax_t maxSizeBytes = 1 * 1024 * 1024 * 1024; + uintmax_t sizeCheckPeriodBytes = std::max(maxSizeBytes / 10, 1); + }; + + FileLogSink(std::filesystem::path path, Options options = {}); ~FileLogSink(); - void Write(const std::string_view str) override { stream_sink.Write(str); } + void Write(const std::string_view str) override; private: + void CheckSize(); + + const std::filesystem::path path; + Options options; std::ofstream stream; StreamLogSink stream_sink{ stream }; + uintmax_t bytesRemainingUntilSizeCheck = (std::numeric_limits::max)(); }; class ThreadSafeLogSink final : public LogSink {