Skip to content
Extraits de code Groupes Projets
Vérifiée Valider 3592c012 rédigé par Kubat's avatar Kubat
Parcourir les fichiers

LOG: Add the base LogSinkDispatcher class and the flush mechanism for the LogSink

parent 21457a79
Aucune branche associée trouvée
Aucune étiquette associée trouvée
1 requête de fusion!21Add clean logs support + dependent MR
......@@ -2,10 +2,17 @@
using namespace Vivy;
LogSinkDispatcher::~LogSinkDispatcher() noexcept {}
LogSink::~LogSink() noexcept {}
Logger::~Logger() noexcept { parentLogSink->closeLoggerClients(); }
LogMessage::~LogMessage() noexcept { parentLogger->sendLogMessage(*this); }
const std::string_view
LogSinkDispatcher::getDispatcherName() const noexcept
{
return dispatcherName;
}
const chrono::milliseconds
LogMessage::getTimeStamp() const noexcept
{
......@@ -46,6 +53,21 @@ LogSink::recieveLogMessage(const Logger *const logger, LogMessage const &msg) no
std::tuple<const std::string_view, const LogMessage>{ logger->getCategoryView(), msg });
}
// Flush all LogMessages to all of the LogSinkDispatchers. Also clear the message queue.
void
LogSink::flush() noexcept
{
const std::lock_guard<std::mutex> messageQueueLockGuard(messageQueueLock);
for (std::weak_ptr<LogSinkDispatcher> weakDispatcher : logDispatchers) {
std::shared_ptr<LogSinkDispatcher> dispatcher = weakDispatcher.lock();
if (dispatcher) {
for (const auto &[category, msg] : messageQueue)
dispatcher->handleLogMessage(category, msg);
}
}
messageQueue.clear();
}
std::shared_ptr<LogSink>
LogSink::newSink() noexcept
{
......@@ -61,6 +83,12 @@ LogSink::registerLoggerClient(std::shared_ptr<Logger> logger) noexcept
clientLoggers.push_back(logger);
}
void
LogSink::registerLogDispatcher(std::shared_ptr<LogSinkDispatcher> dispatcher) noexcept
{
logDispatchers.push_back(dispatcher);
}
void
LogSink::closeLoggerClients() noexcept
{
......@@ -72,18 +100,18 @@ LogSink::closeLoggerClients() noexcept
std::shared_ptr<Logger>
LogSink::getLoggerClient(const std::string_view category) const
{
auto end = std::end(clientLoggers);
auto it = std::find_if(std::begin(clientLoggers), end,
[category](const std::weak_ptr<Logger> &weakPtr) {
std::shared_ptr<Logger> sharedPtr = weakPtr.lock();
return sharedPtr && (sharedPtr->getCategoryView() == category);
});
if (it == end)
throw std::logic_error("Logger was not found");
std::shared_ptr<Logger> sharedPtr = (*it).lock();
if (sharedPtr == nullptr)
throw std::logic_error("Logger has expired");
return sharedPtr;
return getSharedPtr(clientLoggers, [category](std::shared_ptr<Logger> ptr) noexcept -> bool {
return ptr->getCategoryView() == category;
});
}
std::shared_ptr<LogSinkDispatcher>
LogSink::getLogDispatcher(const std::string_view name) const
{
return getSharedPtr(logDispatchers,
[name](std::shared_ptr<LogSinkDispatcher> ptr) noexcept -> bool {
return ptr->getDispatcherName() == name;
});
}
LogMessage
......
......@@ -49,6 +49,21 @@ class LogSink {
explicit LogSink() noexcept = default;
template <typename T>
std::shared_ptr<T> getSharedPtr(std::vector<std::weak_ptr<T>> weakPtrList, auto nameCheck) const
{
std::shared_ptr<T> sharedPtr(nullptr);
auto end = std::end(weakPtrList);
auto it = std::find_if(std::begin(weakPtrList), end,
[&nameCheck, &sharedPtr](const std::weak_ptr<T> &weakPtr) {
sharedPtr = weakPtr.lock();
return sharedPtr && nameCheck(sharedPtr);
});
if (it == end || sharedPtr == nullptr)
throw std::logic_error("Pointer was not found or has expired");
return sharedPtr;
}
public:
static std::shared_ptr<LogSink> newSink() noexcept;
~LogSink() noexcept;
......@@ -56,13 +71,18 @@ public:
void recieveLogMessage(const Logger *const, LogMessage const &) noexcept;
void registerLoggerClient(std::shared_ptr<Logger>) noexcept;
void registerLogDispatcher(std::shared_ptr<LogSinkDispatcher>) noexcept;
void closeLoggerClients() noexcept;
std::shared_ptr<Logger> getLoggerClient(const std::string_view category) const;
std::shared_ptr<LogSinkDispatcher> getLogDispatcher(const std::string_view category) const;
void flush() noexcept;
private:
std::mutex messageQueueLock{};
std::vector<std::tuple<const std::string_view, const LogMessage>> messageQueue;
std::vector<std::weak_ptr<Logger>> clientLoggers;
std::vector<std::weak_ptr<LogSinkDispatcher>> logDispatchers;
};
// Message to be logged, constructed by a logger then send
......@@ -103,11 +123,32 @@ private:
Logger *const parentLogger;
};
// A LogSinkDispatcher will excavate LogMessages from the Sink and do something
// with them (save to a file, display in stderr/Vivy console, etc).
class LogSinkDispatcher : public std::enable_shared_from_this<LogSinkDispatcher> {
VIVY_UNMOVABLE_OBJECT(LogSinkDispatcher)
const std::string dispatcherName;
protected:
explicit LogSinkDispatcher(LogSink *const sink, const std::string_view name) noexcept
: dispatcherName(name)
{
std::shared_ptr<LogSinkDispatcher> self = shared_from_this();
sink->registerLogDispatcher(self);
}
public:
const std::string_view getDispatcherName() const noexcept;
virtual ~LogSinkDispatcher() noexcept;
virtual void handleLogMessage(const std::string_view, const LogMessage &) noexcept = 0;
};
// A logger class, a client to LogSink. Will generate and send instances of
// LogMessage.
class Logger : public std::enable_shared_from_this<Logger> {
class Logger final : public std::enable_shared_from_this<Logger> {
VIVY_UNMOVABLE_OBJECT(Logger)
friend class LogSink;
LogSink *const parentLogSink;
const std::string logCategory;
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter