feaat(statusbar)

This commit is contained in:
whaffman 2025-10-27 15:16:03 +01:00
parent 12106441f1
commit b27b3fe2d2
7 changed files with 66 additions and 4 deletions

View File

@ -29,4 +29,9 @@ std::string Channel::printContext(const std::map<std::string, std::string> &cont
} }
return ss.str(); return ss.str();
}
bool Channel::isStdOut() const
{
return false;
} }

View File

@ -18,6 +18,7 @@ class Channel
const std::map<std::string, std::string> &context = {}) const std::map<std::string, std::string> &context = {})
= 0; = 0;
[[nodiscard]] virtual bool isStdOut() const;
protected: protected:
[[nodiscard]] static std::string printContext(const std::map<std::string, std::string> &context); [[nodiscard]] static std::string printContext(const std::map<std::string, std::string> &context);

View File

@ -1,7 +1,6 @@
#include <webserv/log/Log.hpp>
#include <webserv/log/Channel.hpp> // for Channel #include <webserv/log/Channel.hpp> // for Channel
#include <webserv/log/FileChannel.hpp> // for FileChannel #include <webserv/log/FileChannel.hpp> // for FileChannel
#include <webserv/log/Log.hpp>
#include <webserv/log/StdoutChannel.hpp> // for StdoutChannel #include <webserv/log/StdoutChannel.hpp> // for StdoutChannel
#include <chrono> // for duration_cast, operator-, steady_clock, duration, seconds #include <chrono> // for duration_cast, operator-, steady_clock, duration, seconds
@ -66,8 +65,21 @@ void Log::log(Level level, const std::string &message, const std::map<std::strin
{ {
for (auto &it : channels_) for (auto &it : channels_)
{ {
std::string statusBackup = _statusMessage;
bool wasActive = _statusActive;
// extendedMessage += " | " + message; // extendedMessage += " | " + message;
if (it.second->isStdOut() && _statusActive)
{
// Clear status line before logging to stdout
clearStatus();
}
it.second->log(level, message, context); it.second->log(level, message, context);
if (it.second->isStdOut() && wasActive)
{
// Reprint status line after logging to stdout
status(statusBackup);
}
} }
} }
@ -173,4 +185,35 @@ Log::Level Log::stringToLogLevel(const std::string &level)
} }
} }
return Level::Info; // Default fallback return Level::Info; // Default fallback
}
std::string Log::_statusMessage;
bool Log::_statusActive = false;
void Log::status(const std::string &message)
{
_statusMessage = message;
_statusActive = true;
// Save cursor position, move to bottom, clear line, print status, restore cursor
std::cout << "\033[s" // Save cursor position
<< "\033[999;0H" // Move to bottom row
<< "\033[2K" // Clear entire line
<< "\033[7m" // Reverse video (inverted colors)
<< message << "\033[0m" // Reset formatting
<< "\033[u" // Restore cursor position
<< std::flush;
}
void Log::clearStatus()
{
if (_statusActive)
{
_statusActive = false;
std::cout << "\033[s" // Save cursor position
<< "\033[999;0H" // Move to bottom row
<< "\033[2K" // Clear entire line
<< "\033[u" // Restore cursor position
<< std::flush;
}
} }

View File

@ -63,6 +63,9 @@ class Log
static void error(const std::string &message, const std::map<std::string, std::string> &context = {}); static void error(const std::string &message, const std::map<std::string, std::string> &context = {});
static void fatal(const std::string &message, const std::map<std::string, std::string> &context = {}); static void fatal(const std::string &message, const std::map<std::string, std::string> &context = {});
static void status(const std::string &message);
static void clearStatus();
static std::string logLevelToString(Level level); static std::string logLevelToString(Level level);
static const char *logLevelToColor(Level level); static const char *logLevelToColor(Level level);
static std::string logLevelToColoredString(Level level); static std::string logLevelToColoredString(Level level);
@ -71,6 +74,8 @@ class Log
static void clearChannels(); static void clearChannels();
private: private:
static std::string _statusMessage;
static bool _statusActive;
Log(); Log();
~Log() = default; ~Log() = default;

View File

@ -1,6 +1,5 @@
#include <webserv/log/StdoutChannel.hpp>
#include <webserv/log/Log.hpp> // for Log #include <webserv/log/Log.hpp> // for Log
#include <webserv/log/StdoutChannel.hpp>
#include <iomanip> // for operator<<, setfill, setw #include <iomanip> // for operator<<, setfill, setw
#include <iostream> // for basic_ostream, operator<<, basic_ostream::operator<<, cerr, cout, flush, ostream #include <iostream> // for basic_ostream, operator<<, basic_ostream::operator<<, cerr, cout, flush, ostream
@ -16,4 +15,9 @@ void StdoutChannel::log(const Log::Level &logLevel, const std::string &message,
out << message << '\n'; out << message << '\n';
out << printContext(context); out << printContext(context);
out << std::flush; out << std::flush;
}
bool StdoutChannel::isStdOut() const
{
return true;
} }

View File

@ -20,4 +20,6 @@ class StdoutChannel : public Channel
void log(const Log::Level &logLevel, const std::string &message, void log(const Log::Level &logLevel, const std::string &message,
const std::map<std::string, std::string> &context = {}) override; const std::map<std::string, std::string> &context = {}) override;
[[nodiscard]] bool isStdOut() const override;
}; };

View File

@ -312,6 +312,8 @@ void Server::run()
struct epoll_event events[MAX_EVENTS]; // NOLINT struct epoll_event events[MAX_EVENTS]; // NOLINT
while (stop_ == 0) while (stop_ == 0)
{ {
std::string status = "Active connections: " + std::to_string(clients_.size());
Log::status(status);
pollSockets(); pollSockets();
pollClients(); pollClients();
handleEpoll(events, MAX_EVENTS); // NOLINT (cppcoreguidelines-pro-bounds-pointer-arithmetic) handleEpoll(events, MAX_EVENTS); // NOLINT (cppcoreguidelines-pro-bounds-pointer-arithmetic)