diff --git a/webserv/client/Client.cpp b/webserv/client/Client.cpp index 1a6cc2d..47f4f07 100644 --- a/webserv/client/Client.cpp +++ b/webserv/client/Client.cpp @@ -1,4 +1,3 @@ -#include "webserv/log/LogLevel.hpp" #include "webserv/socket/Socket.hpp" #include diff --git a/webserv/log/Channel.cpp b/webserv/log/Channel.cpp new file mode 100644 index 0000000..8ba7543 --- /dev/null +++ b/webserv/log/Channel.cpp @@ -0,0 +1,4 @@ +#include + + +Channel::Channel(Log::Level logLevel) : logLevel_(logLevel) {} \ No newline at end of file diff --git a/webserv/log/Channel.hpp b/webserv/log/Channel.hpp index 6fcf7ef..81f63c9 100644 --- a/webserv/log/Channel.hpp +++ b/webserv/log/Channel.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include + #include #include @@ -10,7 +10,7 @@ class Channel { public: Channel() = default; - Channel(LogLevel logLevel); + Channel(Log::Level logLevel); virtual ~Channel() = default; Channel(const Channel &other) = delete; @@ -18,9 +18,9 @@ class Channel Channel &operator=(const Channel &other) = delete; Channel &&operator=(const Channel &&other) = delete; - virtual void log(LogLevel &logLevel, const std::string &message, + virtual void log(Log::Level &logLevel, const std::string &message, const std::map &context = {}) = 0; protected: - LogLevel logLevel_{LogLevel::LOGLVL_TRACE}; + Log::Level logLevel_{Log::Level::Trace}; }; \ No newline at end of file diff --git a/webserv/log/Channnel.cpp b/webserv/log/Channnel.cpp deleted file mode 100644 index 8bcd5e9..0000000 --- a/webserv/log/Channnel.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#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 a22c8e3..745deab 100644 --- a/webserv/log/FileChannel.cpp +++ b/webserv/log/FileChannel.cpp @@ -1,12 +1,13 @@ -#include "webserv/log/LogLevel.hpp" + #include +#include #include #include #include -FileChannel::FileChannel(const std::string &filename, std::ios_base::openmode mode, LogLevel logLevel) +FileChannel::FileChannel(const std::string &filename, std::ios_base::openmode mode, Log::Level logLevel) : Channel(logLevel), filename_(filename), fileStream_(filename, mode) { if (!fileStream_.is_open()) @@ -23,7 +24,7 @@ FileChannel::~FileChannel() } } -void FileChannel::log(LogLevel &logLevel, const std::string &message, const std::map &context) +void FileChannel::log(Log::Level &logLevel, const std::string &message, const std::map &context) { if (logLevel < logLevel_) { @@ -42,7 +43,7 @@ void FileChannel::log(LogLevel &logLevel, const std::string &message, const std: // Format the log message fileStream_ << "[" << std::put_time(tm, "%Y-%m-%d %H:%M:%S") << "] " - << "[" << logLevelToString(logLevel) << "] " << message << '\n'; + << "[" << Log::logLevelToString(logLevel) << "] " << message << '\n'; // Log the context if it exists if (!context.empty()) diff --git a/webserv/log/FileChannel.hpp b/webserv/log/FileChannel.hpp index bd2a8fd..684f42a 100644 --- a/webserv/log/FileChannel.hpp +++ b/webserv/log/FileChannel.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include + #include #include @@ -10,7 +10,7 @@ class FileChannel : public Channel { public: - FileChannel(const std::string &filename, std::ios_base::openmode mode, LogLevel logLevel = LogLevel::LOGLVL_TRACE); + FileChannel(const std::string &filename, std::ios_base::openmode mode, Log::Level logLevel = Log::Level::Trace); FileChannel(const FileChannel &other) = delete; FileChannel(const FileChannel &&other) = delete; @@ -18,7 +18,7 @@ class FileChannel : public Channel FileChannel &&operator=(const FileChannel &&other) = delete; ~FileChannel(); - void log(LogLevel &logLevel, const std::string &message, + void log(Log::Level &logLevel, const std::string &message, const std::map &context = {}) override; private: diff --git a/webserv/log/Log.cpp b/webserv/log/Log.cpp index 72b927e..47bb362 100644 --- a/webserv/log/Log.cpp +++ b/webserv/log/Log.cpp @@ -13,7 +13,7 @@ Log::Log() start_time_ = std::chrono::steady_clock::now(); } -void Log::setStdoutChannel(LogLevel logLevel) +void Log::setStdoutChannel(Log::Level logLevel) { Log &log = getInstance(); if (log.channels_.contains("stdout")) @@ -30,7 +30,7 @@ void Log::setStdoutChannel(LogLevel logLevel) } } -void Log::setFileChannel(const std::string &filename, std::ios_base::openmode mode, LogLevel logLevel) +void Log::setFileChannel(const std::string &filename, std::ios_base::openmode mode, Log::Level logLevel) { Log &log = getInstance(); if (log.channels_.contains("file")) @@ -53,7 +53,7 @@ Log &Log::getInstance() return instance; } -void Log::log(LogLevel level, const std::string &message, const std::map &context, +void Log::log(Log::Level level, const std::string &message, const std::map &context, const std::source_location &location) { for (auto &it : channels_) @@ -81,35 +81,76 @@ int Log::getElapsedTime() void Log::trace(const std::string &message, const std::map &context, const std::source_location &location) { - getInstance().log(LogLevel::LOGLVL_TRACE, message, context, location); + getInstance().log(Log::Level::Trace, message, context, location); } void Log::debug(const std::string &message, const std::map &context, const std::source_location &location) { - getInstance().log(LogLevel::LOGLVL_DEBUG, message, context, location); + getInstance().log(Log::Level::Debug, message, context, location); } void Log::info(const std::string &message, const std::map &context, const std::source_location &location) { - getInstance().log(LogLevel::LOGLVL_INFO, message, context, location); + getInstance().log(Log::Level::Info, message, context, location); } void Log::warning(const std::string &message, const std::map &context, - const std::source_location &location) + const std::source_location &location) { - getInstance().log(LogLevel::LOGLVL_WARN, message, context, location); + getInstance().log(Log::Level::Warn, message, context, location); } void Log::error(const std::string &message, const std::map &context, const std::source_location &location) { - getInstance().log(LogLevel::LOGLVL_ERROR, message, context, location); + getInstance().log(Log::Level::Error, message, context, location); } void Log::fatal(const std::string &message, const std::map &context, const std::source_location &location) { - getInstance().log(LogLevel::LOGLVL_FATAL, message, context, location); + getInstance().log(Log::Level::Fatal, message, context, location); +} + +std::string Log::logLevelToString(Log::Level level) +{ + for (const auto &mapping : LOG_LEVEL_MAP) + { + if (mapping.level == level) + { + return std::string(mapping.name); + } + } + return "UNKNOWN"; +} + +const char *Log::logLevelToColor(Log::Level level) +{ + for (const auto &mapping : LOG_LEVEL_MAP) + { + if (mapping.level == level) + { + return mapping.color; + } + } + return "\033[0m"; // Default to reset +} + +std::string Log::logLevelToColoredString(Log::Level level) +{ + return std::string(Log::logLevelToColor(level)) + Log::logLevelToString(level) + "\033[0m"; +} + +Log::Level Log::stringToLogLevel(const std::string &level) +{ + for (const auto &mapping : LOG_LEVEL_MAP) + { + if (mapping.name == level) + { + return mapping.level; + } + } + return Log::Level::Info; // Default fallback } \ No newline at end of file diff --git a/webserv/log/Log.hpp b/webserv/log/Log.hpp index 361e5b5..206be9a 100644 --- a/webserv/log/Log.hpp +++ b/webserv/log/Log.hpp @@ -1,45 +1,42 @@ #pragma once -#include -#include +// #include +#include #include #include #include #include #include +#include #include -/* -TODO ACTUALLY WE USE C++20 SO WE CAN USE std::source_location TO AUTOMATICALLY CAPTURE FILE, LINE, FUNCTION - -#include - -void log(LogLevel level, const std::string& message, - std::source_location location = std::source_location::current()) { - std::cout << "File: " << location.file_name() << std::endl; - std::cout << "Line: " << location.line() << std::endl; - std::cout << "Function: " << location.function_name() << std::endl; -} - -No macros needed!!!! -*/ class Channel; // Forward declaration class Log { public: + enum class Level : uint8_t + { + Trace = 0, + Debug = 1, + Info = 2, + Warn = 3, + Error = 4, + Fatal = 5 + }; + Log(const Log &other) = delete; Log(const Log &&other) = delete; Log &operator=(const Log &other) = delete; Log &&operator=(const Log &&other) = delete; - void log(LogLevel level, const std::string &message, const std::map &context, + void log(Level level, const std::string &message, const std::map &context, const std::source_location &location); static void setFileChannel(const std::string &filename, std::ios_base::openmode mode = std::ios_base::app, - LogLevel logLevel = LogLevel::LOGLVL_TRACE); - static void setStdoutChannel(LogLevel logLevel = LogLevel::LOGLVL_TRACE); + Level logLevel = Level::Trace); + static void setStdoutChannel(Level logLevel = Level::Trace); static int getElapsedTime(); @@ -55,6 +52,10 @@ class Log const std::source_location &location = std::source_location::current()); static void fatal(const std::string &message, const std::map &context = {}, const std::source_location &location = std::source_location::current()); + static std::string logLevelToString(Level level); + static const char *logLevelToColor(Level level); + static std::string logLevelToColoredString(Level level); + static Log::Level stringToLogLevel(const std::string &level); private: Log(); @@ -64,4 +65,21 @@ class Log std::chrono::steady_clock::time_point start_time_; std::unordered_map> channels_; -}; \ No newline at end of file + + + + struct LogLevelMapping + { + Log::Level level; + std::string_view name; + const char *color; + }; + + constexpr static std::array LOG_LEVEL_MAP = { + {{.level = Log::Level::Trace, .name = "TRACE", .color = "\033[36m"}, + {.level = Log::Level::Debug, .name = "DEBUG", .color = "\033[90m"}, + {.level = Log::Level::Info, .name = "INFO", .color = "\033[37m"}, + {.level = Log::Level::Warn, .name = "WARN", .color = "\033[33m"}, + {.level = Log::Level::Error, .name = "ERROR", .color = "\033[31m"}, + {.level = Log::Level::Fatal, .name = "FATAL", .color = "\033[1;31m"}}}; +}; diff --git a/webserv/log/LogLevel.hpp b/webserv/log/LogLevel.hpp deleted file mode 100644 index 4357af3..0000000 --- a/webserv/log/LogLevel.hpp +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -// TODO LOG_LEVEL_MAP should not be in the global namespace, but i do think this is the nice way? lets refactor this to -// the log class or use a seperate namespace or put everything in a log namespace except for the class, then everything -// has Log:: - -enum class LogLevel : uint8_t -{ - LOGLVL_TRACE = 0, - LOGLVL_DEBUG = 1, - LOGLVL_INFO = 2, - LOGLVL_WARN = 3, - LOGLVL_ERROR = 4, - LOGLVL_FATAL = 5 -}; - -// ANSI color codes -namespace LogColors -{ -constexpr const char *RESET = "\033[0m"; -constexpr const char *TRACE_COLOR = "\033[36m"; // Cyan -constexpr const char *DEBUG_COLOR = "\033[90m"; // Bright black (gray) -constexpr const char *INFO_COLOR = "\033[37m"; // White -constexpr const char *WARN_COLOR = "\033[33m"; // Yellow -constexpr const char *ERROR_COLOR = "\033[31m"; // Red -constexpr const char *FATAL_COLOR = "\033[1;31m"; // Bold red -} // namespace LogColors - -// Constexpr bidirectional mapping -struct LogLevelMapping -{ - LogLevel level; - std::string_view name; - const char *color; -}; - -constexpr std::array LOG_LEVEL_MAP = { - {{.level = LogLevel::LOGLVL_TRACE, .name = "TRACE", .color = LogColors::TRACE_COLOR}, - {.level = LogLevel::LOGLVL_DEBUG, .name = "DEBUG", .color = LogColors::DEBUG_COLOR}, - {.level = LogLevel::LOGLVL_INFO, .name = "INFO", .color = LogColors::INFO_COLOR}, - {.level = LogLevel::LOGLVL_WARN, .name = "WARN", .color = LogColors::WARN_COLOR}, - {.level = LogLevel::LOGLVL_ERROR, .name = "ERROR", .color = LogColors::ERROR_COLOR}, - {.level = LogLevel::LOGLVL_FATAL, .name = "FATAL", .color = LogColors::FATAL_COLOR}}}; - -inline std::string logLevelToString(LogLevel level) -{ - for (const auto &mapping : LOG_LEVEL_MAP) - { - if (mapping.level == level) - { - return std::string(mapping.name); - } - } - return "UNKNOWN"; -} - -inline const char *logLevelToColor(LogLevel level) -{ - for (const auto &mapping : LOG_LEVEL_MAP) - { - if (mapping.level == level) - { - return mapping.color; - } - } - return LogColors::RESET; -} - -inline std::string logLevelToColoredString(LogLevel level) -{ - return std::string(logLevelToColor(level)) + logLevelToString(level) + LogColors::RESET; -} - -inline LogLevel stringToLogLevel(const std::string &level) -{ - for (const auto &mapping : LOG_LEVEL_MAP) - { - if (mapping.name == level) - { - return mapping.level; - } - } - return LogLevel::LOGLVL_INFO; // Default fallback -} \ No newline at end of file diff --git a/webserv/log/StdoutChannel.cpp b/webserv/log/StdoutChannel.cpp index 6a80bde..658b42a 100644 --- a/webserv/log/StdoutChannel.cpp +++ b/webserv/log/StdoutChannel.cpp @@ -2,17 +2,17 @@ #include #include -#include + #include #include #include -StdoutChannel::StdoutChannel(LogLevel logLevel) : Channel(logLevel) {} +StdoutChannel::StdoutChannel(Log::Level logLevel) : Channel(logLevel) {} StdoutChannel::~StdoutChannel() {} -void StdoutChannel::log(LogLevel &logLevel, const std::string &message, +void StdoutChannel::log(Log::Level &logLevel, const std::string &message, const std::map &context) { if (logLevel < logLevel_) @@ -20,7 +20,7 @@ void StdoutChannel::log(LogLevel &logLevel, const std::string &message, return; } std::cout << "[" << std::setw(3) << std::setfill('0') << Log::getElapsedTime() << "] "; - std::string prefix = "[" + logLevelToColoredString(logLevel) + "] "; + std::string prefix = "[" + Log::logLevelToColoredString(logLevel) + "] "; std::cout << prefix; std::cout << message; if (!context.empty()) diff --git a/webserv/log/StdoutChannel.hpp b/webserv/log/StdoutChannel.hpp index 7a1c1d1..2c21a48 100644 --- a/webserv/log/StdoutChannel.hpp +++ b/webserv/log/StdoutChannel.hpp @@ -5,7 +5,7 @@ class StdoutChannel : public Channel { public: - StdoutChannel(LogLevel logLevel = LogLevel::LOGLVL_TRACE); + StdoutChannel(Log::Level logLevel = Log::Level::Trace); StdoutChannel(const StdoutChannel &other) = delete; StdoutChannel(const StdoutChannel &&other) = delete; @@ -14,6 +14,6 @@ class StdoutChannel : public Channel ~StdoutChannel(); - void log(LogLevel &logLevel, const std::string &message, + void log(Log::Level &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 1fcbae6..6c81ee3 100644 --- a/webserv/main.cpp +++ b/webserv/main.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include @@ -16,8 +15,8 @@ int main(int argc, char **argv) std::cerr << "Usage: " << argv[0] << " \n"; // NOLINT return 1; } - Log::setFileChannel("webserv.log", std::ios_base::app, LogLevel::LOGLVL_TRACE); - Log::setStdoutChannel(LogLevel::LOGLVL_INFO); + Log::setFileChannel("webserv.log", std::ios_base::app, Log::Level::Trace); + Log::setStdoutChannel(Log::Level::Info); Log::info("\n======================\nStarting webserv...\n======================\n"); ConfigManager::getInstance().init(argv[1]); // NOLINT Server server(ConfigManager::getInstance());