Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
Logger.cpp
Go to the documentation of this file.
1#include "Logger.h"
2
3Logger* Logger::instance = nullptr;
4
6 if (!Logger::instance) {
7 Logger::instance = new Logger();
8 }
9 return Logger::instance;
10}
11
12Logger::Logger() : exitFlag(false) {
13 if (!std::filesystem::exists(this->logDirectory)) {
14 if(std::filesystem::create_directories(this->logDirectory)) {
15
16 }
17 else {
18 std::cerr << "Error during logDirectory creation. " << std::endl;
19 }
20 }
21 loggingThread = std::thread(&Logger::processQueue, this);
22 this->threadId = loggingThread.get_id();
23}
24
26 {
27 std::unique_lock<std::mutex> lock(queueMutex);
28 exitFlag = true;
29 }
30 conditionVar.notify_all();
31 loggingThread.join();
32
33 for (auto& logFilePair : logFiles) {
34 logFilePair.second.close();
35 }
36}
37
39 this->level = level;
40}
41
42void Logger::setLogDirectory(const std::string& directory, std::size_t maxSize) {
43 logDirectory = directory;
44 maxFileSize = maxSize;
45 if (!std::filesystem::exists(logDirectory)) {
46 std::filesystem::create_directories(logDirectory);
47 }
48}
49
50void Logger::setEnabled(bool enabled) {
51 this->enabled = enabled;
52}
53
54std::string Logger::toString(LogLevel level) {
55 switch (level) {
56 case LogLevel::INFO: return "INFO";
57 case LogLevel::WARN: return "WARN";
58 case LogLevel::ERROR: return "ERROR";
59 case LogLevel::DEBUG: return "DEBUG";
60 case LogLevel::TRACE: return "TRACE";
61 case LogLevel::VERBOSE: return "VERBOSE";
62 default: return "UNKNOWN";
63 }
64}
65
66
67std::string Logger::currentDateTime() {
68 std::time_t now = std::time(nullptr);
69 char buf[80];
70 std::strftime(buf, sizeof(buf), "%Y-%m-%d_%H", std::localtime(&now));
71 return std::string(buf);
72}
73
74std::string Logger::getLogFilenameWithSuffix(const std::string& baseName, int suffix) {
75 std::ostringstream filename;
76 filename << baseName << "_" << suffix << ".log";
77 return filename.str();
78}
79
80std::string Logger::getLogFilenameForThread(std::thread::id threadId) {
81 std::ostringstream filename;
82 filename << logDirectory << "/log_" << currentDateTime() << "_thread_" << threadId;
83 return filename.str();
84}
85
86std::ofstream& Logger::getLogFile(std::thread::id threadId) {
87 std::lock_guard<std::mutex> lock(logFileMutex);
88
89 auto it = logFiles.find(threadId);
90 if (it == logFiles.end()) {
91 std::string filepath = getLogFilenameForThread(threadId) + ".log";
92 logFiles[threadId].open(filepath, std::ios_base::app);
93 if (!logFiles[threadId].is_open()) {
94 throw std::runtime_error("Cannot open log file for thread");
95 }
96 }
97 return logFiles[threadId];
98}
99
100void Logger::rotateLogFile(std::thread::id threadId) {
101 std::lock_guard<std::mutex> lock(logFileMutex);
102
103 auto& logFile = logFiles[threadId];
104 logFile.close();
105
106 std::string baseFilepath = getLogFilenameForThread(threadId);
107 std::string oldFilepath = baseFilepath + ".log";
108
109 int suffix = 1;
110 std::string newFilename = getLogFilenameWithSuffix(baseFilepath, suffix);
111 while (std::filesystem::exists(newFilename)) {
112 ++suffix;
113 newFilename = getLogFilenameWithSuffix(baseFilepath, suffix);
114 }
115 std::filesystem::rename(oldFilepath, newFilename);
116
117 logFiles[threadId].open(oldFilepath, std::ios_base::app);
118 if (!logFiles[threadId].is_open()) {
119 throw std::runtime_error("Cannot open new log file for thread");
120 }
121}
122
123void Logger::processQueue() {
124 while (!exitFlag) {
125 std::unique_lock<std::mutex> lock(queueMutex);
126 conditionVar.wait(lock, [this] { return !logQueue.empty() || exitFlag; });
127
128 while (!logQueue.empty()) {
129 std::string logEntry = logQueue.front();
130 logQueue.pop();
131 lock.unlock();
132
133 std::string logFilePath = getLogFilenameForThread(this->threadId) + ".log";
134
135 if (std::filesystem::exists(logFilePath) && std::filesystem::file_size(logFilePath) >= maxFileSize) {
136 rotateLogFile(threadId);
137 std::cout << logFilePath << " " << std::filesystem::file_size(logFilePath) << std::endl;
138 logFilePath = getLogFilenameForThread(threadId) + ".log";
139 }
140
141 std::ofstream& logFile = getLogFile(this->threadId);
142 logFile << logEntry << std::endl;
143
144 lock.lock();
145 }
146 }
147
148 while (!logQueue.empty()) {
149 std::string logEntry = logQueue.front();
150 logQueue.pop();
151
152 std::string logFilePath = getLogFilenameForThread(threadId) + ".log";
153
154 if (std::filesystem::exists(logFilePath) && std::filesystem::file_size(logFilePath) >= maxFileSize) {
155 rotateLogFile(threadId);
156 logFilePath = getLogFilenameForThread(threadId) + ".log";
157 }
158
159 std::ofstream& logFile = getLogFile(threadId);
160 logFile << logEntry << std::endl;
161 }
162}
A singleton logging utility supporting multiple logging levels and concurrent logging to file and ter...
Definition Logger.h:53
std::thread::id threadId
Definition Logger.h:108
void setEnabled(bool enabled)
Enables or disables the Logger.
Definition Logger.cpp:50
std::string getLogFilenameWithSuffix(const std::string &baseName, int suffix)
Retrieves a log filename with a suffix.
Definition Logger.cpp:74
void setLevel(LogLevel level)
Sets the logging level.
Definition Logger.cpp:38
LogLevel
Logging levels supported by the Logger.
Definition Logger.h:59
void setLogDirectory(const std::string &directory, std::size_t maxSize=10048576)
Sets the directory for storing log files.
Definition Logger.cpp:42
~Logger()
Destructor for Logger, ensures graceful shutdown of logging.
Definition Logger.cpp:25
std::string getLogFilenameForThread(std::thread::id threadId)
Retrieves the log filename for the specified thread.
Definition Logger.cpp:80
static Logger * getInstance()
Retrieves the singleton instance of the Logger.
Definition Logger.cpp:5