blob: c57216be22e1913acf3470130573fb5cd5c22d0a [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#include "logger.hpp"
2
3#include <sstream>
4
5namespace vpd
6{
Sunny Srivastava5779d972025-08-08 01:45:23 -05007std::shared_ptr<Logger> Logger::m_loggerInstance;
8
9void Logger::logMessage(std::string_view i_message,
10 const PlaceHolder& i_placeHolder,
11 const types::PelInfoTuple* i_pelTuple,
12 const std::source_location& i_location)
13{
14 std::ostringstream l_log;
15 l_log << "FileName: " << i_location.file_name() << ","
16 << " Line: " << i_location.line() << " " << i_message;
17
Souvik Roya5e18b82025-09-25 05:59:56 +000018 if ((i_placeHolder == PlaceHolder::COLLECTION) && m_collectionLogger)
Sunny Srivastava5779d972025-08-08 01:45:23 -050019 {
20 // Log it to a specific place.
Souvik Roya8c3c092025-09-11 10:49:29 +000021 m_collectionLogger->logMessage(l_log.str());
Sunny Srivastava5779d972025-08-08 01:45:23 -050022 }
23 else if (i_placeHolder == PlaceHolder::PEL)
24 {
25 if (i_pelTuple)
26 {
27 // LOG PEL
28 // This should call create PEL API from the event logger.
29 return;
30 }
31 std::cout << "Pel info tuple required to log PEL for message <" +
32 l_log.str() + ">"
33 << std::endl;
34 }
Souvik Roya5e18b82025-09-25 05:59:56 +000035 else if ((i_placeHolder == PlaceHolder::VPD_WRITE) && m_vpdWriteLogger)
36 {
Souvik Roya8c3c092025-09-11 10:49:29 +000037 m_vpdWriteLogger->logMessage(l_log.str());
Souvik Roya5e18b82025-09-25 05:59:56 +000038 }
Sunny Srivastava5779d972025-08-08 01:45:23 -050039 else
40 {
41 // Default case, let it go to journal.
42 std::cout << l_log.str() << std::endl;
43 }
44}
45
Souvik Roya5e18b82025-09-25 05:59:56 +000046void Logger::initiateVpdCollectionLogging() noexcept
47{
48 try
49 {
50 /* TODO:
51 - check /var/lib/vpd for number "collection.*" log file
52 - if 3 collection_[0-2].log files are found
53 - delete collection_1.log
54 - create collection logger object with collection_1.log
55 parameter
56 - else
57 - create collection logger object with collection_(n+1).log
58 parameter*/
Souvik Roy0fb5c3b2025-09-15 08:18:25 +000059 m_collectionLogger.reset(
Souvik Royf8587362025-09-25 09:56:20 +000060 new AsyncFileLogger("/var/lib/vpd/collection.log", 4096));
Souvik Roya5e18b82025-09-25 05:59:56 +000061 }
62 catch (const std::exception& l_ex)
63 {
64 logMessage("Failed to initialize collection logger. Error: " +
65 std::string(l_ex.what()));
66 }
67}
68
Souvik Roy6bd74ad2025-09-12 06:24:06 +000069void SyncFileLogger::logMessage(const std::string_view& i_message)
70{
71 try
72 {
73 if (++m_currentNumEntries > m_maxEntries)
74 {
75 rotateFile();
76 }
77 m_fileStream << timestamp() << " : " << i_message << std::endl;
78 }
79 catch (const std::exception& l_ex)
80 {
81 // log message to journal if we fail to log to file
82 auto l_logger = Logger::getLoggerInstance();
83 l_logger->logMessage(i_message);
84 }
85}
86
Souvik Royf8587362025-09-25 09:56:20 +000087void AsyncFileLogger::logMessage(const std::string_view& i_message)
Souvik Roy0fb5c3b2025-09-15 08:18:25 +000088{
89 try
90 {
Souvik Royf8587362025-09-25 09:56:20 +000091 // acquire lock on queue
92 std::unique_lock<std::mutex> l_lock(m_mutex);
93
94 // push message to queue
95 m_messageQueue.emplace(timestamp() + " : " + std::string(i_message));
96
97 // notify log worker thread
98 m_cv.notify_one();
Souvik Roy0fb5c3b2025-09-15 08:18:25 +000099 }
100 catch (const std::exception& l_ex)
101 {
Souvik Royf8587362025-09-25 09:56:20 +0000102 // log message to journal if we fail to push message to queue
103 Logger::getLoggerInstance()->logMessage(i_message);
Souvik Roy0fb5c3b2025-09-15 08:18:25 +0000104 }
105}
106
107void AsyncFileLogger::fileWorker() noexcept
108{
Souvik Royf8587362025-09-25 09:56:20 +0000109 // create lock object on mutex
110 std::unique_lock<std::mutex> l_lock(m_mutex);
111
112 // infinite loop
113 while (true)
114 {
115 // check for exit conditions
116 if (!m_fileStream.is_open() || m_stopLogging)
117 {
118 break;
119 }
120
121 // wait for notification from log producer
122 m_cv.wait(l_lock,
123 [this] { return m_stopLogging || !m_messageQueue.empty(); });
124
125 // flush the queue
126 while (!m_messageQueue.empty())
127 {
128 // read the first message in queue
129 const auto l_logMessage = m_messageQueue.front();
130 try
131 {
132 // pop the message from queue
133 m_messageQueue.pop();
134
135 // unlock mutex on queue
136 l_lock.unlock();
137
138 if (++m_currentNumEntries > m_maxEntries)
139 {
140 rotateFile();
141 }
142
143 // flush the message to file
144 m_fileStream << l_logMessage << std::endl;
145
146 // lock mutex on queue
147 l_lock.lock();
148 }
149 catch (const std::exception& l_ex)
150 {
151 // log message to journal if we fail to push message to queue
152 Logger::getLoggerInstance()->logMessage(l_logMessage);
153
154 // check if we need to reacquire lock before continuing to flush
155 // queue
156 if (!l_lock.owns_lock())
157 {
158 l_lock.lock();
159 }
160 }
161 } // queue flush loop
162 } // thread loop
Souvik Roy0fb5c3b2025-09-15 08:18:25 +0000163}
164
Souvik Roya8c3c092025-09-11 10:49:29 +0000165void ILogFileHandler::rotateFile(
166 [[maybe_unused]] const unsigned i_numEntriesToDelete)
Souvik Roy6bd74ad2025-09-12 06:24:06 +0000167{
168 /* TODO:
169 - delete specified number of oldest entries from beginning of file
170 - rewrite file to move existing logs to beginning of file
171 */
172 m_currentNumEntries = m_maxEntries - i_numEntriesToDelete;
173}
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500174namespace logging
175{
176void logMessage(std::string_view message, const std::source_location& location)
177{
178 std::ostringstream log;
179 log << "FileName: " << location.file_name() << ","
180 << " Line: " << location.line() << " " << message;
181
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500182 std::cout << log.str() << std::endl;
183}
184} // namespace logging
185} // namespace vpd