blob: 53fb7d9b40418275d2258ba648f657c2f6fe92a6 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#pragma once
#include <fstream>
#include <iostream>
#include <mutex>
#include <regex>
// Log levels
enum LogLevel {
DEBUG = 0,
INFO = 1,
WARN = 2,
ERR = 3
};
// Convert LogLevel to string
inline const char* logLevelToString(const LogLevel level) {
switch (level) {
case DEBUG: return "DEBUG";
case INFO: return "INFO";
case WARN: return "WARN";
case ERR: return "ERROR";
default: return "UNKNOWN";
}
}
class Logger {
public:
static Logger& getInstance()
{
static Logger instance;
return instance;
}
void setLogFilePath(const std::string& filePath)
{
std::lock_guard lock(mMutex);
if (mLogFile.is_open()) {
mLogFile.close();
}
mLogFile.open(filePath, std::ios::out);
// std::ios::app is an option for appending but dont wanna grow it forever.
}
void setDebugMode(bool debug)
{
std::lock_guard lock(mMutex);
mDebugMode = debug;
}
void logMessage(const LogLevel level, const std::string& message)
{
#if defined(__GNUC__) || defined(__clang__)
std::string functionName = __PRETTY_FUNCTION__;
#elif defined(_MSC_VER)
std::string functionName = __FUNCSIG__;
#else
std::string functionName = "UnknownFunction";
#endif
std::regex classNameRegex(R"((\w+)::\w+\()");
std::smatch match;
std::string className = "UnknownClass";
if (std::regex_search(functionName, match, classNameRegex) && match.size() > 1) {
className = match.str(1);
}
std::lock_guard lock(mMutex);
auto writeLog = [&](std::ostream& stream) {
switch (level) {
case DEBUG:
stream << "[DEBUG] " << message << std::endl;
break;
case INFO:
stream << "[INFO] " << message << std::endl;
break;
case WARN:
stream << "[WARN] " << message << std::endl;
break;
case ERR:
stream << "[ERROR] " << message << std::endl;
break;
}
};
if (mLogFile.is_open()) {
writeLog(mLogFile);
}
}
Logger& operator=(const Logger&) = delete;
private:
Logger() = default;
~Logger()
{
if (mLogFile.is_open()) {
mLogFile.close();
}
}
Logger(const Logger&) = delete;
std::ofstream mLogFile;
std::mutex mMutex;
#if !defined(NDEBUG) || defined(CMAKE_BUILD_TYPE_RELWITHDEBINFO)
bool mDebugMode = true; // Auto-enable in debug/RelWithDebInfo builds
#else
bool mDebugMode = false; // Disable in release builds
#endif
};
|