diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2025-03-05 23:44:56 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2025-03-07 18:03:03 +0800 |
| commit | c37bd3e34f5840773949bb55848cda3af6688d20 (patch) | |
| tree | 1d31ea7c3cf8811ea294da9c094027a9e805dfcb | |
| parent | aa21e4ea0687fd0c8d333161f5ec31a580512e9e (diff) | |
refactor: logging system
| -rw-r--r-- | src/format.hpp | 76 | ||||
| -rw-r--r-- | src/log.cpp | 26 | ||||
| -rw-r--r-- | src/log.hpp | 36 | ||||
| -rw-r--r-- | src/server.cpp | 4 | ||||
| -rw-r--r-- | src/server.hpp | 3 | ||||
| -rw-r--r-- | src/session.cpp | 60 | ||||
| -rw-r--r-- | src/session.hpp | 12 |
7 files changed, 178 insertions, 39 deletions
diff --git a/src/format.hpp b/src/format.hpp new file mode 100644 index 0000000..2630b7f --- /dev/null +++ b/src/format.hpp @@ -0,0 +1,76 @@ +#pragma once +#include <format> +#include <string> + +enum class eFormatType { + RAW, // No formatting at all + STANDARD, // Standard message format + SYSTEM, // System message format + ERROR, // Error message format + CHAT, // Chat message format (username: message) + INFO, // Info level log format + WARN, // Warning level log format + FATAL // Fatal level log format +}; + +class CFormatter { + public: + template <typename... Args> + static std::string fmt(eFormatType type, std::format_string<Args...> fmt, Args &&...args, bool addNewline = true) { + std::string formatted = std::vformat(fmt.get(), std::make_format_args(args...)); + if (addNewline && !formatted.empty() && formatted.back() != '\n') + formatted += '\n'; + + switch (type) { + case eFormatType::RAW: + return formatted; + case eFormatType::STANDARD: + return "[MSG] " + formatted; + case eFormatType::SYSTEM: + return "[SYS] " + formatted; + case eFormatType::ERROR: + return "[ERR] " + formatted; + case eFormatType::CHAT: + return formatted; // handled by chatFmt + case eFormatType::INFO: + return "[INFO] " + formatted; + case eFormatType::WARN: + return "[WARN] " + formatted; + case eFormatType::FATAL: + return "[FATAL] " + formatted; + default: + return formatted; + } + } + + template <typename... Args> + static std::string chatFmt(const std::string &username, std::format_string<Args...> fmt, Args &&...args) { + std::string formatted = std::vformat(fmt.get(), std::make_format_args(args...)); + return std::format("{}: {}", username, formatted); + } +}; + +template <typename... Args> +inline std::string fmtRaw(std::format_string<Args...> fmt, Args &&...args, bool addNewline = true) { + return CFormatter::fmt(eFormatType::RAW, fmt, std::forward<Args>(args)..., addNewline); +} + +template <typename... Args> +inline std::string fmtStd(std::format_string<Args...> fmt, Args &&...args, bool addNewline = true) { + return CFormatter::fmt(eFormatType::STANDARD, fmt, std::forward<Args>(args)..., addNewline); +} + +template <typename... Args> +inline std::string fmtSys(std::format_string<Args...> fmt, Args &&...args, bool addNewline = true) { + return CFormatter::fmt(eFormatType::SYSTEM, fmt, std::forward<Args>(args)..., addNewline); +} + +template <typename... Args> +inline std::string fmtErr(std::format_string<Args...> fmt, Args &&...args, bool addNewline = true) { + return CFormatter::fmt(eFormatType::ERROR, fmt, std::forward<Args>(args)..., addNewline); +} + +template <typename... Args> +inline std::string fmtChat(const std::string &username, std::format_string<Args...> fmt, Args &&...args) { + return CFormatter::chatFmt(username, fmt, std::forward<Args>(args)...); +} diff --git a/src/log.cpp b/src/log.cpp new file mode 100644 index 0000000..8cd3ded --- /dev/null +++ b/src/log.cpp @@ -0,0 +1,26 @@ +#include "log.hpp" + +void log(eLogLevel level, std::string str) { + // Use CFormatter for the prefix part + std::string prefixed; + switch (level) { + case INFO: + prefixed = CFormatter::fmt<const std::string &>(eFormatType::STANDARD, "{}", str); + str = useColors ? "\033[1;32m" + prefixed + "\033[0m" : prefixed; // green + break; + case WARN: + prefixed = CFormatter::fmt<const std::string &>(eFormatType::SYSTEM, "{}", str); + str = useColors ? "\033[1;33m" + prefixed + "\033[0m" : prefixed; // yellow + break; + case ERROR: + prefixed = CFormatter::fmt<const std::string &>(eFormatType::ERROR, "{}", str); + str = useColors ? "\033[1;31m" + prefixed + "\033[0m" : prefixed; // red + break; + case FATAL: + prefixed = CFormatter::fmt<const std::string &>(eFormatType::ERROR, "{}", str); + str = useColors ? "\033[1;35m" + prefixed + "\033[0m" : prefixed; // magenta + break; + } + + std::println("{}", str); // Changed to print since we're managing the newline ourselves +} diff --git a/src/log.hpp b/src/log.hpp index 1ee401e..a6c6ea2 100644 --- a/src/log.hpp +++ b/src/log.hpp @@ -1,12 +1,28 @@ #pragma once - -#include <map> +#include "format.hpp" +#include <chrono> +#include <format> +#include <print> #include <string> -typedef enum { - LOG_LEVEL_DEBUG = 0, - LOG_LEVEL_INFO, - LOG_LEVEL_WARN, - LOG_LEVEL_ERROR, - LOG_LEVEL_FATAL, - LOG_LEVEL_MAX -} eLogLevel; + +enum eLogLevel : int8_t { + INFO = 0, + WARN, + ERROR, + FATAL +}; + +inline bool useColors = true; + +void log(eLogLevel level, std::string str); + +template <typename... Args> +void log(eLogLevel level, std::format_string<Args...> fmt, Args &&...args) { + const auto now = std::chrono::system_clock::now(); + const auto hms = std::chrono::hh_mm_ss{now - std::chrono::floor<std::chrono::days>(now)}; + std::string timeStamp = std::format("[{}] ", hms); + + std::string msg = CFormatter::fmt(eFormatType::RAW, fmt, std::forward<Args>(args)...); + + log(level, timeStamp + msg); +} diff --git a/src/server.cpp b/src/server.cpp index 18a20ea..7893893 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -27,10 +27,6 @@ CServer::~CServer() { m_sockfd.reset(); } -void CServer::log(const eLogLevel loglevel, const std::string &message) const { - std::println("[{}]: {}", "a", message); -} - Hyprutils::OS::CFileDescriptor CServer::getSocket() const { return m_sockfd.duplicate(); } diff --git a/src/server.hpp b/src/server.hpp index 9cca9ac..2cd15b3 100644 --- a/src/server.hpp +++ b/src/server.hpp @@ -1,16 +1,13 @@ #pragma once #include "FileDescriptor.hpp" -#include "log.hpp" #include <memory> #include <netinet/in.h> -#include <string> class CServer { public: CServer(uint16_t port); ~CServer(); - void log(const eLogLevel loglevel, const std::string &message) const; Hyprutils::OS::CFileDescriptor getSocket() const; private: diff --git a/src/session.cpp b/src/session.cpp index bfadb5d..d18dbd6 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -1,8 +1,9 @@ #include "session.hpp" +#include "log.hpp" #include <cerrno> #include <cstring> -#include <print> #include <sys/socket.h> +#include <unistd.h> CSession::CSession(Hyprutils::OS::CFileDescriptor sockfd) : m_sockfd(std::move(sockfd)) { @@ -11,29 +12,34 @@ CSession::CSession(Hyprutils::OS::CFileDescriptor sockfd) } CSession::~CSession() { + onDisconnect(); m_sockfd.reset(); } void CSession::onConnect() const { - std::println("Client connected"); + log(INFO, "Client connected"); } void CSession::onDisconnect() const { - std::println("Client disconnected"); + log(INFO, "Client disconnected"); } void CSession::onErrno(eEventType eventType) const { const auto err = strerror(errno); switch (eventType) { case READ: - std::println("Error while reading: {}", err); + log(ERROR, "Error while reading: {}", err); case WRITE: - std::println("Error while writing: {}", err); + log(ERROR, "Error while writing: {}", err); } } -void CSession::onRecv(SRecvData &data) const { - std::println("Received: {}", data.data, data.dataSize); +void CSession::onRecv(const SRecvData &data) const { + log(INFO, "Received: {}", data.data, data.dataSize); +} + +void CSession::onSend(const std::string &msg) const { + log(INFO, "Sent: {}", msg); } void CSession::recvManager() { @@ -55,26 +61,32 @@ CSession::SRecvData CSession::read() { recvData.good = false; onDisconnect(); } + onRecv(recvData); return recvData; } -CSession::SRecvData CSession::read(std::string &msg) { - write(msg); +CSession::SRecvData CSession::read(const std::string &msg) { + write(eFormatType::STANDARD, "{}", msg, false); return read(); } void CSession::run() { onConnect(); - // std::jthread recvThread(&CSession::recvManager, this); registerSession(); recvManager(); } bool CSession::registerSession() { - SRecvData recvData = read((std::string &)"Name: "); + SRecvData recvData = read("Name: "); if (!recvData.good) return false; + + if (recvData.data[0] == '\n' || recvData.data[0] == ' ') { + write("Name cannot be empty", eFormatType::ERROR); + registerSession(); + } + m_name = recvData.data; std::println("Client registered as: {}", m_name); @@ -83,17 +95,29 @@ bool CSession::registerSession() { } bool CSession::isValid() const { - return m_sockfd.isValid() && !m_name.empty(); + if (!m_sockfd.isValid() || m_name.empty()) + return false; + + if (send(m_sockfd.get(), "", 0, MSG_NOSIGNAL) < 0) + return false; + + return true; } -bool CSession::write(const std::string &msg) const { - bool bad = false; - ssize_t sentSize = send(m_sockfd.get(), msg.c_str(), msg.size(), 0); - if (sentSize < 0) { - bad = true; +template <typename... Args> +bool CSession::write(eFormatType type, std::format_string<Args...> fmt, Args &&...args) const { + std::string msg = CFormatter::fmt(type, fmt, std::forward<Args>(args)...); + + if (send(m_sockfd.get(), msg.c_str(), msg.size(), 0) < 0) { onErrno(WRITE); + return false; } - return bad; + onSend(msg); + return true; +} + +bool CSession::write(const std::string &msg, eFormatType type) const { + return write(type, "{}", msg); } std::string CSession::getName() const { diff --git a/src/session.hpp b/src/session.hpp index 9dc3f0f..0c5e4f9 100644 --- a/src/session.hpp +++ b/src/session.hpp @@ -1,6 +1,7 @@ #pragma once #include "FileDescriptor.hpp" +#include "format.hpp" #include <string> class CSession { @@ -15,9 +16,11 @@ class CSession { std::string getName() const; bool isValid() const; SRecvData read(); - SRecvData read(std::string &msg); - bool write(const std::string &msg) const; - void run(); + SRecvData read(const std::string &msg); + bool write(const std::string &msg, eFormatType type) const; + template <typename... Args> + bool write(eFormatType type, std::format_string<Args...> fmt, Args &&...args) const; + void run(); private: enum eEventType { @@ -31,6 +34,7 @@ class CSession { void onConnect() const; void onDisconnect() const; void onErrno(eEventType) const; - void onRecv(SRecvData &data) const; + void onRecv(const SRecvData &data) const; + void onSend(const std::string &msg) const; friend class CSessionManager; }; |
