blob: c57216be22e1913acf3470130573fb5cd5c22d0a [file] [log] [blame]
#include "logger.hpp"
#include <sstream>
namespace vpd
{
std::shared_ptr<Logger> Logger::m_loggerInstance;
void Logger::logMessage(std::string_view i_message,
const PlaceHolder& i_placeHolder,
const types::PelInfoTuple* i_pelTuple,
const std::source_location& i_location)
{
std::ostringstream l_log;
l_log << "FileName: " << i_location.file_name() << ","
<< " Line: " << i_location.line() << " " << i_message;
if ((i_placeHolder == PlaceHolder::COLLECTION) && m_collectionLogger)
{
// Log it to a specific place.
m_collectionLogger->logMessage(l_log.str());
}
else if (i_placeHolder == PlaceHolder::PEL)
{
if (i_pelTuple)
{
// LOG PEL
// This should call create PEL API from the event logger.
return;
}
std::cout << "Pel info tuple required to log PEL for message <" +
l_log.str() + ">"
<< std::endl;
}
else if ((i_placeHolder == PlaceHolder::VPD_WRITE) && m_vpdWriteLogger)
{
m_vpdWriteLogger->logMessage(l_log.str());
}
else
{
// Default case, let it go to journal.
std::cout << l_log.str() << std::endl;
}
}
void Logger::initiateVpdCollectionLogging() noexcept
{
try
{
/* TODO:
- check /var/lib/vpd for number "collection.*" log file
- if 3 collection_[0-2].log files are found
- delete collection_1.log
- create collection logger object with collection_1.log
parameter
- else
- create collection logger object with collection_(n+1).log
parameter*/
m_collectionLogger.reset(
new AsyncFileLogger("/var/lib/vpd/collection.log", 4096));
}
catch (const std::exception& l_ex)
{
logMessage("Failed to initialize collection logger. Error: " +
std::string(l_ex.what()));
}
}
void SyncFileLogger::logMessage(const std::string_view& i_message)
{
try
{
if (++m_currentNumEntries > m_maxEntries)
{
rotateFile();
}
m_fileStream << timestamp() << " : " << i_message << std::endl;
}
catch (const std::exception& l_ex)
{
// log message to journal if we fail to log to file
auto l_logger = Logger::getLoggerInstance();
l_logger->logMessage(i_message);
}
}
void AsyncFileLogger::logMessage(const std::string_view& i_message)
{
try
{
// acquire lock on queue
std::unique_lock<std::mutex> l_lock(m_mutex);
// push message to queue
m_messageQueue.emplace(timestamp() + " : " + std::string(i_message));
// notify log worker thread
m_cv.notify_one();
}
catch (const std::exception& l_ex)
{
// log message to journal if we fail to push message to queue
Logger::getLoggerInstance()->logMessage(i_message);
}
}
void AsyncFileLogger::fileWorker() noexcept
{
// create lock object on mutex
std::unique_lock<std::mutex> l_lock(m_mutex);
// infinite loop
while (true)
{
// check for exit conditions
if (!m_fileStream.is_open() || m_stopLogging)
{
break;
}
// wait for notification from log producer
m_cv.wait(l_lock,
[this] { return m_stopLogging || !m_messageQueue.empty(); });
// flush the queue
while (!m_messageQueue.empty())
{
// read the first message in queue
const auto l_logMessage = m_messageQueue.front();
try
{
// pop the message from queue
m_messageQueue.pop();
// unlock mutex on queue
l_lock.unlock();
if (++m_currentNumEntries > m_maxEntries)
{
rotateFile();
}
// flush the message to file
m_fileStream << l_logMessage << std::endl;
// lock mutex on queue
l_lock.lock();
}
catch (const std::exception& l_ex)
{
// log message to journal if we fail to push message to queue
Logger::getLoggerInstance()->logMessage(l_logMessage);
// check if we need to reacquire lock before continuing to flush
// queue
if (!l_lock.owns_lock())
{
l_lock.lock();
}
}
} // queue flush loop
} // thread loop
}
void ILogFileHandler::rotateFile(
[[maybe_unused]] const unsigned i_numEntriesToDelete)
{
/* TODO:
- delete specified number of oldest entries from beginning of file
- rewrite file to move existing logs to beginning of file
*/
m_currentNumEntries = m_maxEntries - i_numEntriesToDelete;
}
namespace logging
{
void logMessage(std::string_view message, const std::source_location& location)
{
std::ostringstream log;
log << "FileName: " << location.file_name() << ","
<< " Line: " << location.line() << " " << message;
std::cout << log.str() << std::endl;
}
} // namespace logging
} // namespace vpd