diff --git a/src/services/impl/logger_service.cpp b/src/services/impl/logger_service.cpp index 20163c6..268a166 100644 --- a/src/services/impl/logger_service.cpp +++ b/src/services/impl/logger_service.cpp @@ -19,15 +19,12 @@ LogLevel LoggerService::GetLevel() const { void LoggerService::SetOutputFile(const std::string& filename) { std::lock_guard lock(impl_->mutex_); - if (impl_->fileStream_) { - impl_->fileStream_->close(); - } - impl_->fileStream_ = std::make_unique(filename, std::ios::app); - if (!impl_->fileStream_->is_open()) { - // Fallback to console if file can't be opened - std::cerr << "Failed to open log file: " << filename << std::endl; - impl_->fileStream_.reset(); - } + impl_->SetOutputFile(filename); +} + +void LoggerService::SetMaxLinesPerFile(size_t maxLines) { + std::lock_guard lock(impl_->mutex_); + impl_->SetMaxLinesPerFile(maxLines); } void LoggerService::EnableConsoleOutput(bool enable) { diff --git a/src/services/impl/logger_service.hpp b/src/services/impl/logger_service.hpp index d20067a..62639e5 100644 --- a/src/services/impl/logger_service.hpp +++ b/src/services/impl/logger_service.hpp @@ -3,6 +3,7 @@ #include "../interfaces/i_logger.hpp" #include #include +#include #include #include #include @@ -16,12 +17,23 @@ namespace sdl3cpp::services::impl { // Implementation class that holds all the logging logic class LoggerImpl { public: + static constexpr size_t kDefaultMaxLinesPerFile = 10000; + std::atomic level_; bool consoleEnabled_; std::unique_ptr fileStream_; std::mutex mutex_; + std::filesystem::path baseFilePath_; + size_t maxLinesPerFile_; + size_t currentLineCount_; + size_t currentFileIndex_; - LoggerImpl() : level_(LogLevel::INFO), consoleEnabled_(true) {} + LoggerImpl() + : level_(LogLevel::INFO), + consoleEnabled_(true), + maxLinesPerFile_(kDefaultMaxLinesPerFile), + currentLineCount_(0), + currentFileIndex_(0) {} ~LoggerImpl() { if (fileStream_) { @@ -66,8 +78,69 @@ public: if (fileStream_) { *fileStream_ << message << std::endl; fileStream_->flush(); + ++currentLineCount_; + RotateFileIfNeeded(); } } + + void SetOutputFile(const std::string& filename) { + if (fileStream_) { + fileStream_->close(); + } + fileStream_.reset(); + + baseFilePath_ = filename; + currentLineCount_ = 0; + currentFileIndex_ = 0; + + if (!baseFilePath_.empty()) { + OpenLogFile(currentFileIndex_); + } + } + + void SetMaxLinesPerFile(size_t maxLines) { + maxLinesPerFile_ = maxLines; + } + + std::filesystem::path BuildLogFilePath(size_t index) const { + if (baseFilePath_.empty() || index == 0) { + return baseFilePath_; + } + + std::filesystem::path basePath(baseFilePath_); + std::string stem = basePath.stem().string(); + std::string extension = basePath.extension().string(); + std::string rotatedName = stem + "." + std::to_string(index) + extension; + + return basePath.parent_path() / rotatedName; + } + + void OpenLogFile(size_t index) { + if (baseFilePath_.empty()) { + return; + } + + std::filesystem::path logPath = BuildLogFilePath(index); + fileStream_ = std::make_unique(logPath, std::ios::out | std::ios::trunc); + if (!fileStream_->is_open()) { + std::cerr << "Failed to open log file: " << logPath.string() << std::endl; + fileStream_.reset(); + } + } + + void RotateFileIfNeeded() { + if (maxLinesPerFile_ == 0 || currentLineCount_ < maxLinesPerFile_) { + return; + } + + if (fileStream_) { + fileStream_->close(); + } + + ++currentFileIndex_; + currentLineCount_ = 0; + OpenLogFile(currentFileIndex_); + } }; /** @@ -85,6 +158,7 @@ public: void SetLevel(LogLevel level) override; LogLevel GetLevel() const override; void SetOutputFile(const std::string& filename) override; + void SetMaxLinesPerFile(size_t maxLines) override; void EnableConsoleOutput(bool enable) override; void Log(LogLevel level, const std::string& message) override; void Trace(const std::string& message) override; @@ -105,4 +179,4 @@ private: std::unique_ptr impl_; }; -} // namespace sdl3cpp::services::impl \ No newline at end of file +} // namespace sdl3cpp::services::impl diff --git a/src/services/interfaces/i_logger.hpp b/src/services/interfaces/i_logger.hpp index 9cc33f3..d851dfc 100644 --- a/src/services/interfaces/i_logger.hpp +++ b/src/services/interfaces/i_logger.hpp @@ -44,6 +44,13 @@ public: */ virtual void SetOutputFile(const std::string& filename) = 0; + /** + * @brief Set the maximum number of log lines per file before rotation. + * + * @param maxLines Max lines per log file, or 0 to disable rotation + */ + virtual void SetMaxLinesPerFile(size_t maxLines) = 0; + /** * @brief Enable or disable console output. * @@ -125,4 +132,4 @@ public: virtual void TraceVariable(const std::string& name, double value) = 0; }; -} // namespace sdl3cpp::services \ No newline at end of file +} // namespace sdl3cpp::services