From bac66d2a0b771add340397f5ff77dafe7d61b86a Mon Sep 17 00:00:00 2001 From: whaffman Date: Sun, 21 Sep 2025 20:49:25 +0200 Subject: [PATCH] Implement logging level support in Channel and its derived classes - Added LogLevel parameter to Channel constructor and updated derived classes (FileChannel, StdoutChannel) to accept it. - Modified log methods to respect the logging level, preventing lower priority logs from being processed. - Updated Log class to set logging levels for stdout and file channels. - Adjusted main function to initialize logging with specified levels. --- webserv/log/Channel.hpp | 4 ++++ webserv/log/Channnel.cpp | 3 +++ webserv/log/FileChannel.cpp | 7 ++++++- webserv/log/FileChannel.hpp | 2 +- webserv/log/Log.cpp | 33 ++++++++++++++++++++++++--------- webserv/log/Log.hpp | 5 +++-- webserv/log/StdoutChannel.cpp | 14 +++++++++++++- webserv/log/StdoutChannel.hpp | 9 +++++++++ webserv/main.cpp | 3 ++- 9 files changed, 65 insertions(+), 15 deletions(-) create mode 100644 webserv/log/Channnel.cpp diff --git a/webserv/log/Channel.hpp b/webserv/log/Channel.hpp index c9f5c36..6fcf7ef 100644 --- a/webserv/log/Channel.hpp +++ b/webserv/log/Channel.hpp @@ -10,6 +10,7 @@ class Channel { public: Channel() = default; + Channel(LogLevel logLevel); virtual ~Channel() = default; Channel(const Channel &other) = delete; @@ -19,4 +20,7 @@ class Channel virtual void log(LogLevel &logLevel, const std::string &message, const std::map &context = {}) = 0; + + protected: + LogLevel logLevel_{LogLevel::LOGLVL_TRACE}; }; \ No newline at end of file diff --git a/webserv/log/Channnel.cpp b/webserv/log/Channnel.cpp new file mode 100644 index 0000000..8bcd5e9 --- /dev/null +++ b/webserv/log/Channnel.cpp @@ -0,0 +1,3 @@ +#include + +Channel::Channel(LogLevel logLevel) : logLevel_(logLevel) {} \ No newline at end of file diff --git a/webserv/log/FileChannel.cpp b/webserv/log/FileChannel.cpp index 87ed95f..4e96d8e 100644 --- a/webserv/log/FileChannel.cpp +++ b/webserv/log/FileChannel.cpp @@ -5,7 +5,8 @@ #include #include -FileChannel::FileChannel(const std::string &filename) : filename_(filename), fileStream_(filename, std::ios::trunc) +FileChannel::FileChannel(const std::string &filename, LogLevel logLevel) + : Channel(logLevel), filename_(filename), fileStream_(filename, std::ios::trunc) { if (!fileStream_.is_open()) { @@ -23,6 +24,10 @@ FileChannel::~FileChannel() void FileChannel::log(LogLevel &logLevel, const std::string &message, const std::map &context) { + if (logLevel < logLevel_) + { + return; + } if (!fileStream_.is_open()) { std::cerr << "Log file is not open: " << filename_ << '\n'; diff --git a/webserv/log/FileChannel.hpp b/webserv/log/FileChannel.hpp index 4c56a95..4e83936 100644 --- a/webserv/log/FileChannel.hpp +++ b/webserv/log/FileChannel.hpp @@ -10,7 +10,7 @@ class FileChannel : public Channel { public: - FileChannel(const std::string &filename); + FileChannel(const std::string &filename, LogLevel logLevel = LogLevel::LOGLVL_TRACE); FileChannel(const FileChannel &other) = delete; FileChannel(const FileChannel &&other) = delete; diff --git a/webserv/log/Log.cpp b/webserv/log/Log.cpp index 13a15e5..840dc7c 100644 --- a/webserv/log/Log.cpp +++ b/webserv/log/Log.cpp @@ -10,10 +10,27 @@ Log::Log() { // get start time start_time_ = std::chrono::steady_clock::now(); - channels_.insert({"stdout", std::unique_ptr(new StdoutChannel())}); + } -void Log::setFile(const std::string &filename) +void Log::setStdoutChannel(LogLevel logLevel) +{ + Log &log = getInstance(); + if (log.channels_.contains("stdout")) + { + log.channels_.erase("stdout"); + } + try + { + log.channels_.insert({"stdout", std::unique_ptr(new StdoutChannel(logLevel))}); + } + catch (const std::exception &e) + { + std::cerr << "Failed to set stdout log channel: " << e.what() << '\n'; + } +} + +void Log::setFileChannel(const std::string &filename, LogLevel logLevel) { Log &log = getInstance(); if (log.channels_.contains("file")) @@ -22,7 +39,7 @@ void Log::setFile(const std::string &filename) } try { - log.channels_.insert({"file", std::unique_ptr(new FileChannel(filename))}); + log.channels_.insert({"file", std::unique_ptr(new FileChannel(filename, logLevel))}); } catch (const std::exception &e) { @@ -39,18 +56,16 @@ Log &Log::getInstance() void Log::log(LogLevel level, const std::string &message, const std::string &channel, const std::map &context) { - auto it = channels_.find(channel); - if (it != channels_.end()) + for (auto &it : channels_) { - it->second->log(level, message, context); + it.second->log(level, message, context); } } void Log::log(LogLevel level, const std::string &message, const std::string &file, int line, const std::string &function, const std::string &channel, const std::map &context) { - auto it = channels_.find(channel); - if (it != channels_.end()) + for (auto &it : channels_) { std::string extendedMessage; extendedMessage += message + " | "; @@ -67,7 +82,7 @@ void Log::log(LogLevel level, const std::string &message, const std::string &fil extendedMessage += " (" + function + ")"; } // extendedMessage += " | " + message; - it->second->log(level, extendedMessage, context); + it.second->log(level, extendedMessage, context); } } diff --git a/webserv/log/Log.hpp b/webserv/log/Log.hpp index bb8f70c..c623b80 100644 --- a/webserv/log/Log.hpp +++ b/webserv/log/Log.hpp @@ -28,8 +28,9 @@ class Log Log &operator=(const Log &other) = delete; Log &&operator=(const Log &&other) = delete; - static void setFile(const std::string &filename); - + static void setFileChannel(const std::string &filename, LogLevel logLevel = LogLevel::LOGLVL_TRACE); + static void setStdoutChannel(LogLevel logLevel = LogLevel::LOGLVL_TRACE); + void log(LogLevel level, const std::string &message, const std::string &channel = "stdout", const std::map &context = {}); diff --git a/webserv/log/StdoutChannel.cpp b/webserv/log/StdoutChannel.cpp index df784a4..6a80bde 100644 --- a/webserv/log/StdoutChannel.cpp +++ b/webserv/log/StdoutChannel.cpp @@ -1,12 +1,24 @@ -#include +#include "webserv/log/StdoutChannel.hpp" + +#include +#include +#include #include #include #include +StdoutChannel::StdoutChannel(LogLevel logLevel) : Channel(logLevel) {} + +StdoutChannel::~StdoutChannel() {} + void StdoutChannel::log(LogLevel &logLevel, const std::string &message, const std::map &context) { + if (logLevel < logLevel_) + { + return; + } std::cout << "[" << std::setw(3) << std::setfill('0') << Log::getElapsedTime() << "] "; std::string prefix = "[" + logLevelToColoredString(logLevel) + "] "; std::cout << prefix; diff --git a/webserv/log/StdoutChannel.hpp b/webserv/log/StdoutChannel.hpp index bb63b85..7a1c1d1 100644 --- a/webserv/log/StdoutChannel.hpp +++ b/webserv/log/StdoutChannel.hpp @@ -5,6 +5,15 @@ class StdoutChannel : public Channel { public: + StdoutChannel(LogLevel logLevel = LogLevel::LOGLVL_TRACE); + + StdoutChannel(const StdoutChannel &other) = delete; + StdoutChannel(const StdoutChannel &&other) = delete; + StdoutChannel &operator=(const StdoutChannel &other) = delete; + StdoutChannel &&operator=(const StdoutChannel &&other) = delete; + + ~StdoutChannel(); + void log(LogLevel &logLevel, const std::string &message, const std::map &context = {}) override; }; \ No newline at end of file diff --git a/webserv/main.cpp b/webserv/main.cpp index 4ffd60d..c1a6871 100644 --- a/webserv/main.cpp +++ b/webserv/main.cpp @@ -16,7 +16,8 @@ int main(int argc, char **argv) std::cerr << "Usage: " << argv[0] << " \n"; // NOLINT return 1; } - Log::setFile("webserv.log"); + Log::setFileChannel("webserv.log", LogLevel::LOGLVL_WARN); + Log::setStdoutChannel(LogLevel::LOGLVL_TRACE); ConfigManager::getInstance().init(argv[1]); // NOLINT Server server(ConfigManager::getInstance()); server.start();