v2.0.0
Loading...
Searching...
No Matches
mne_logger.cpp
Go to the documentation of this file.
1//=============================================================================================================
18
19//=============================================================================================================
20// INCLUDES
21//=============================================================================================================
22
23#include <iostream>
24#include <string>
25#include "mne_logger.h"
26
27//=============================================================================================================
28// QT INCLUDES
29//=============================================================================================================
30
31#include <QtGlobal>
32#include <QDateTime>
33#include <QMutexLocker>
34#include <QFile>
35#include <QTextStream>
36
37//=============================================================================================================
38// USED NAMESPACES
39//=============================================================================================================
40
41using namespace UTILSLIB;
42
43//=============================================================================================================
44// Definitions
45//=============================================================================================================
46
47#ifdef WIN32
48#include <wchar.h>
49#include <windows.h>
50#define COLOR_INFO "\033[32;1m"
51#define COLOR_DEBUG "\033[32;1m"
52#define COLOR_WARN "\033[33;1m"
53#define COLOR_CRITICAL "\033[31;1m"
54#define COLOR_FATAL "\033[33;1m"
55#define COLOR_RESET "\033[0m"
56#else
57#define COLOR_INFO "\033[32;1m" //green
58#define COLOR_DEBUG "\033[32;1m" //green
59#define COLOR_WARN "\033[33;1m" //yellow
60#define COLOR_CRITICAL "\033[31;1m" //red
61#define COLOR_FATAL "\033[33;1m" //yellow
62#define COLOR_RESET "\033[0m" //reset
63#endif
64
65std::mutex MNELogger::m_mutex;
66QString MNELogger::m_sLogFilePath;
67
68//=============================================================================================================
69// DEFINE MEMBER METHODS
70//=============================================================================================================
71
72bool MNELogger::setLogFile(const QString& sFilePath)
73{
74 std::lock_guard<std::mutex> lock(m_mutex);
75
76 if (sFilePath.isEmpty()) {
77 m_sLogFilePath.clear();
78 return true;
79 }
80
81 //
82 // Make sure the destination is writable now rather than silently dropping
83 // every message later on.
84 //
85 QFile file(sFilePath);
86 if (!file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
87 return false;
88 }
89 file.close();
90
91 m_sLogFilePath = sFilePath;
92
93 return true;
94}
95
96//=============================================================================================================
97
99{
100 std::lock_guard<std::mutex> lock(m_mutex);
101
102 return m_sLogFilePath;
103}
104
105void MNELogger::customLogWriter(QtMsgType type,
106 const QMessageLogContext& context,
107 const QString& msg)
108{
109 Q_UNUSED(context)
110
111 // Map Qt message type to numeric level (must match CMake MNE_LOG_LEVEL values)
112 // 0=DEBUG, 1=INFO, 2=WARN, 3=CRIT, 4=FATAL
113 int msgLevel = 0;
114 switch (type) {
115 case QtDebugMsg:
116 msgLevel = 0;
117 break;
118 case QtInfoMsg:
119 msgLevel = 1;
120 break;
121 case QtWarningMsg:
122 msgLevel = 2;
123 break;
124 case QtCriticalMsg:
125 msgLevel = 3;
126 break;
127 case QtFatalMsg:
128 msgLevel = 4;
129 break;
130 default:
131 msgLevel = 0;
132 break;
133 }
134
135#ifdef MNE_LOG_LEVEL
136 if (msgLevel < MNE_LOG_LEVEL)
137 return;
138#endif
139
140 std::string text = msg.toStdString();
141
142 std::lock_guard<std::mutex> lock(m_mutex);
143
144 //
145 // Mirror the message into the log file when one was configured. This is
146 // kept free of the colour escapes so the file stays readable, and carries
147 // a timestamp because a log that outlives the session needs one.
148 //
149 if (!m_sLogFilePath.isEmpty()) {
150 QFile logFile(m_sLogFilePath);
151 if (logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
152 const char* fileLevel = "";
153 switch (type) {
154 case QtDebugMsg:
155 fileLevel = "DEBUG";
156 break;
157 case QtInfoMsg:
158 fileLevel = "INFO";
159 break;
160 case QtWarningMsg:
161 fileLevel = "WARN";
162 break;
163 case QtCriticalMsg:
164 fileLevel = "CRIT";
165 break;
166 case QtFatalMsg:
167 fileLevel = "FATAL";
168 break;
169 default:
170 fileLevel = "LOG";
171 break;
172 }
173
174 QTextStream stream(&logFile);
175 stream << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz")
176 << " [" << fileLevel << "] "
177 << QString::fromStdString(text).trimmed() << '\n';
178 logFile.close();
179 }
180 }
181
182#ifdef MNE_LOG_MODE_FORMATTED
183 static bool s_startOfLine = true;
184
185 // Determine color and level tag
186 const char* color = COLOR_RESET;
187 const char* level = "";
188 switch (type) {
189 case QtDebugMsg:
190 color = COLOR_DEBUG;
191 level = "[DEBUG] ";
192 break;
193 case QtInfoMsg:
194 color = COLOR_INFO;
195 level = "[INFO] ";
196 break;
197 case QtWarningMsg:
198 color = COLOR_WARN;
199 level = "[WARN] ";
200 break;
201 case QtCriticalMsg:
202 color = COLOR_CRITICAL;
203 level = "[CRIT] ";
204 break;
205 case QtFatalMsg:
206 color = COLOR_FATAL;
207 level = "[FATAL] ";
208 break;
209 default:
210 level = "";
211 break;
212 }
213
214 // Uncomment the following line to include date/time in log prefix:
215 // std::string sDateTime = QDateTime::currentDateTime().toString("dd/MM/yyyy hh:mm:ss.z ").toStdString();
216 std::string sDateTime;
217
218 std::string prefix = std::string(color) + sDateTime + level + COLOR_RESET;
219
220 // Walk through the message character by character.
221 // Print the prefix only at the start of each new line.
222 for (size_t i = 0; i < text.size(); ++i) {
223 if (s_startOfLine && text[i] != '\n') {
224 std::cout << prefix;
225 s_startOfLine = false;
226 }
227 std::cout << text[i];
228 if (text[i] == '\n') {
229 s_startOfLine = true;
230 }
231 }
232
233 if (text.empty() || text.back() != '\n') {
234 std::cout << '\n';
235 s_startOfLine = true;
236 }
237#else
238 // PLAIN mode: raw text, like printf
239 std::cout << text;
240 if (text.empty() || text.back() != '\n') {
241 std::cout << '\n';
242 }
243#endif
244
245 std::cout.flush();
246}
#define COLOR_INFO
#define COLOR_RESET
#define COLOR_DEBUG
#define COLOR_CRITICAL
#define COLOR_WARN
#define COLOR_FATAL
Custom Qt message handler that adds ANSI colour, timestamps and source-location tags to qDebug/qWarni...
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
static void customLogWriter(QtMsgType type, const QMessageLogContext &context, const QString &msg)
static bool setLogFile(const QString &sFilePath)
static QString logFile()