FileLogger:async file logging stub
This commit implements a class to handle asynchronous file logging. It
extends the LogFileHandler class. Logging messages to file from multiple
VPD collection threads synchronously affects the overall VPD collection
time, hence these logs need to be handled asynchronously. This commit
includes stub changes only and actual implementation will be handled in
future commit(s).
Change-Id: I81342e20a10015364d7de5b77531688aeabe6000
Signed-off-by: Souvik Roy <souvikroyofficial10@gmail.com>
diff --git a/vpd-manager/include/logger.hpp b/vpd-manager/include/logger.hpp
index a28e73e..1622426 100644
--- a/vpd-manager/include/logger.hpp
+++ b/vpd-manager/include/logger.hpp
@@ -6,6 +6,8 @@
#include <fstream>
#include <iostream>
#include <memory>
+#include <mutex>
+#include <queue>
#include <source_location>
#include <string_view>
@@ -186,6 +188,71 @@
};
/**
+ * @brief A class to handle asynchronous logging of messages to file
+ *
+ * This class implements methods to log messages asynchronously to a desired
+ * file in the filesystem. It uses a queue for buffering the messages from
+ * caller. The actual file operations are handled by a worker thread.
+ */
+class AsyncFileLogger final : public ILogFileHandler
+{
+ /**
+ * @brief Constructor
+ * Private so that can't be initialized by class(es) other than friends.
+ *
+ * @param[in] i_fileName - Name of the log file
+ * @param[in] i_maxEntries - Maximum number of entries in the log file after
+ * which the file will be rotated
+ */
+ AsyncFileLogger(const std::filesystem::path& i_fileName,
+ const size_t i_maxEntries) :
+ ILogFileHandler(i_fileName, i_maxEntries)
+ {
+ // start worker thread in detached mode
+ std::thread{[this]() { this->fileWorker(); }}.detach();
+ }
+
+ /**
+ * @brief Logger worker thread body
+ */
+ void fileWorker() noexcept;
+
+ public:
+ // Friend class Logger.
+ friend class Logger;
+
+ // deleted methods
+ AsyncFileLogger() = delete;
+ AsyncFileLogger(const AsyncFileLogger&) = delete;
+ AsyncFileLogger(const AsyncFileLogger&&) = delete;
+ AsyncFileLogger operator=(const AsyncFileLogger&) = delete;
+ AsyncFileLogger operator=(const AsyncFileLogger&&) = delete;
+
+ /**
+ * @brief API to log a message to file
+ *
+ * @param[in] i_message - Message to log
+ *
+ * @throw std::runtime_error
+ */
+ void logMessage(const std::string_view& i_message) override;
+
+ // destructor
+ ~AsyncFileLogger()
+ {
+ /* TODO
+ - acquire lock
+ - set log stop flag to true
+ - notify log worker thread
+ */
+ if (m_fileStream.is_open())
+ {
+ m_fileStream.close();
+ }
+ }
+};
+
+/**
* @brief Singleton class to handle error logging for the repository.
*/
class Logger
@@ -245,7 +312,7 @@
*/
void terminateVpdCollectionLogging() noexcept
{
- // TODO: reset VPD collection logger
+ m_collectionLogger.reset();
}
private:
diff --git a/vpd-manager/src/logger.cpp b/vpd-manager/src/logger.cpp
index 254a177..f7acfb4 100644
--- a/vpd-manager/src/logger.cpp
+++ b/vpd-manager/src/logger.cpp
@@ -56,6 +56,8 @@
- else
- create collection logger object with collection_(n+1).log
parameter*/
+ m_collectionLogger.reset(
+ new AsyncFileLogger("/var/lib/vpd/collection.log", 512));
}
catch (const std::exception& l_ex)
{
@@ -82,6 +84,35 @@
}
}
+void AsyncFileLogger::logMessage(
+ [[maybe_unused]] const std::string_view& i_message)
+{
+ try
+ {
+ /* TODO:
+ - acquire lock on queue
+ - push message to queue
+ - notify log worker thread
+ */
+ }
+ catch (const std::exception& l_ex)
+ {
+ auto l_logger = Logger::getLoggerInstance();
+ l_logger->logMessage(i_message);
+ }
+}
+
+void AsyncFileLogger::fileWorker() noexcept
+{
+ /* TODO:
+ - start an infinite loop
+ - check exit conditions and exit if needed
+ - wait for notification from log producer
+ - if notification received, flush the messages from queue to file
+ - rotate file if needed
+ */
+}
+
void ILogFileHandler::rotateFile(
[[maybe_unused]] const unsigned i_numEntriesToDelete)
{