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

@ -30,3 +30,8 @@ std::string Channel::printContext(const std::map<std::string, std::string> &cont
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 = {})
= 0;
[[nodiscard]] virtual bool isStdOut() const;
protected:
[[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/FileChannel.hpp> // for FileChannel
#include <webserv/log/Log.hpp>
#include <webserv/log/StdoutChannel.hpp> // for StdoutChannel
#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_)
{
std::string statusBackup = _statusMessage;
bool wasActive = _statusActive;
// extendedMessage += " | " + message;
if (it.second->isStdOut() && _statusActive)
{
// Clear status line before logging to stdout
clearStatus();
}
it.second->log(level, message, context);
if (it.second->isStdOut() && wasActive)
{
// Reprint status line after logging to stdout
status(statusBackup);
}
}
}
@ -174,3 +186,34 @@ Log::Level Log::stringToLogLevel(const std::string &level)
}
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 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 const char *logLevelToColor(Level level);
static std::string logLevelToColoredString(Level level);
@ -71,6 +74,8 @@ class Log
static void clearChannels();
private:
static std::string _statusMessage;
static bool _statusActive;
Log();
~Log() = default;

View File

@ -1,6 +1,5 @@
#include <webserv/log/StdoutChannel.hpp>
#include <webserv/log/Log.hpp> // for Log
#include <webserv/log/StdoutChannel.hpp>
#include <iomanip> // for operator<<, setfill, setw
#include <iostream> // for basic_ostream, operator<<, basic_ostream::operator<<, cerr, cout, flush, ostream
@ -17,3 +16,8 @@ void StdoutChannel::log(const Log::Level &logLevel, const std::string &message,
out << printContext(context);
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,
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
while (stop_ == 0)
{
std::string status = "Active connections: " + std::to_string(clients_.size());
Log::status(status);
pollSockets();
pollClients();
handleEpoll(events, MAX_EVENTS); // NOLINT (cppcoreguidelines-pro-bounds-pointer-arithmetic)