6
6
7
7
#ifndef _WIN32
8
8
#include < syslog.h>
9
+ #include < unistd.h>
9
10
#elif _WIN32
11
+ #include < io.h>
10
12
#include < windows.h>
11
13
#include < Shlwapi.h>
12
14
#pragma comment(lib, "Shlwapi.lib")
20
22
#include < time.h>
21
23
22
24
23
-
24
- QMutex Logger::_mapLock;
25
+ QMutex Logger::_mapLock;
26
+ QString Logger::_lastError;
27
+ bool Logger::_hasConsole;
25
28
QMap<QString, Logger*> Logger::_loggerMap;
26
29
QAtomicInteger<int > Logger::GLOBAL_MIN_LOG_LEVEL{ static_cast <int >(Logger::UNSET) };
27
30
@@ -31,6 +34,8 @@ namespace
31
34
32
35
#ifndef _WIN32
33
36
const int LogLevelSysLog[] = { LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR };
37
+ #else
38
+ HANDLE consoleHandle = nullptr ;
34
39
#endif
35
40
36
41
const size_t MAX_IDENTIFICATION_LENGTH = 22 ;
@@ -56,10 +61,28 @@ Logger* Logger::getInstance(const QString& name, Logger::LogLevel minLevel)
56
61
if (log == nullptr )
57
62
{
58
63
log = new Logger (name, minLevel);
59
- _loggerMap.insert (name, log ); // compat version, replace it with following line if we have 100% c++11
60
- // LoggerMap.emplace(name, log); // not compat with older linux distro's e.g. wheezy
64
+ _loggerMap.insert (name, log );
61
65
connect (log , &Logger::newLogMessage, LoggerManager::getInstance (), &LoggerManager::handleNewLogMessage);
62
66
connect (log , &Logger::newState, LoggerManager::getInstance (), &LoggerManager::handleNewState);
67
+
68
+ if (_loggerMap.size () == 1 )
69
+ {
70
+ // detect if we can output colorized logs
71
+ #ifdef _WIN32
72
+ consoleHandle = GetStdHandle (STD_OUTPUT_HANDLE);
73
+ _hasConsole = (consoleHandle != nullptr );
74
+ #else
75
+ _hasConsole = isatty (fileno (stdin));
76
+ #endif
77
+
78
+ T_LOG_MESSAGE t;
79
+ t.utime = QDateTime::currentDateTime ().toMSecsSinceEpoch ();
80
+ t.loggerName = name;
81
+ t.level = LogLevel::INFO;
82
+ t.levelString = LogLevelStrings[t.level ];
83
+ t.message = (_hasConsole) ? " TTY is attached to the log output" : " TTY is not attached to the log output" ;
84
+ LoggerManager::getInstance ()->handleNewLogMessage (t);
85
+ }
63
86
}
64
87
65
88
return log ;
@@ -154,28 +177,69 @@ Logger::~Logger()
154
177
155
178
void Logger::write (const Logger::T_LOG_MESSAGE& message)
156
179
{
157
- QString location;
158
- if (message.level == Logger::DEBUG)
180
+ if (_hasConsole)
159
181
{
160
- location = QString ( " %1:%2:%3() | " )
161
- . arg (message. fileName )
162
- . arg (message. line )
163
- . arg (message.function );
164
- }
165
-
166
- QString name = (message.appName + " " + message. loggerName ). trimmed ();
167
- name. resize (MAX_IDENTIFICATION_LENGTH, ' ' );
168
-
169
- const QDateTime timestamp = QDateTime::fromMSecsSinceEpoch (message. utime );
182
+ static QMutex localMutex;
183
+ QString location, prefix, sufix;
184
+
185
+ if (message.level == Logger::DEBUG)
186
+ {
187
+ location = QString ( " %1:%2:%3() | " )
188
+ . arg (message.fileName )
189
+ . arg (message. line )
190
+ . arg (message. function );
191
+ }
170
192
171
- std::cout << QString (" %1 %2 : <%3> %4%5" )
172
- .arg (timestamp.toString (" yyyy-MM-ddThh:mm:ss.zzz" ))
173
- .arg (name)
174
- .arg (LogLevelStrings[message.level ])
175
- .arg (location)
176
- .arg (message.message )
177
- .toStdString ()
178
- << std::endl;
193
+ QString name = (message.appName + " " + message.loggerName ).trimmed ();
194
+ name.resize (MAX_IDENTIFICATION_LENGTH, ' ' );
195
+
196
+ const QDateTime timestamp = QDateTime::fromMSecsSinceEpoch (message.utime );
197
+
198
+ localMutex.lock ();
199
+
200
+ #ifndef _WIN32
201
+ prefix = " \033 [0m" ;
202
+ sufix = " \033 [36;1m" ;
203
+ #else
204
+ SetConsoleTextAttribute (consoleHandle, 7 );
205
+ #endif
206
+
207
+ std::cout << QString (" %1%2 %3 : " )
208
+ .arg (prefix)
209
+ .arg (timestamp.toString (" hh:mm:ss.zzz" ))
210
+ .arg (name)
211
+ .toStdString ();
212
+
213
+ #ifndef _WIN32
214
+ switch (message.level )
215
+ {
216
+ case (Logger::INFO): prefix = " \033 [32;1m" ; break ;
217
+ case (Logger::WARNING): prefix = " \033 [33;1m" ; break ;
218
+ case (Logger::ERRORR): prefix = " \033 [31;1m" ; break ;
219
+ default : break ;
220
+ }
221
+ #else
222
+ switch (message.level )
223
+ {
224
+ case (Logger::INFO):SetConsoleTextAttribute (consoleHandle, 10 ); break ;
225
+ case (Logger::WARNING):SetConsoleTextAttribute (consoleHandle, 14 ); break ;
226
+ case (Logger::ERRORR):SetConsoleTextAttribute (consoleHandle, 12 ); break ;
227
+ default : break ;
228
+ }
229
+ #endif
230
+ std::cout << QString (" %1<%2> %3%4%5" )
231
+ .arg (prefix)
232
+ .arg (LogLevelStrings[message.level ])
233
+ .arg (location)
234
+ .arg (message.message )
235
+ .arg (sufix)
236
+ .toStdString ()
237
+ << std::endl;
238
+ #ifdef _WIN32
239
+ SetConsoleTextAttribute (consoleHandle, 11 );
240
+ #endif
241
+ localMutex.unlock ();
242
+ }
179
243
180
244
newLogMessage (message);
181
245
}
@@ -258,8 +322,6 @@ void Logger::Message(LogLevel level, const char* sourceFile, const char* func, u
258
322
}
259
323
}
260
324
261
- QString Logger::_lastError;
262
-
263
325
QString Logger::getLastError ()
264
326
{
265
327
return _lastError;
0 commit comments