diff options
Diffstat (limited to 'common/log.cpp')
-rw-r--r-- | common/log.cpp | 104 |
1 files changed, 82 insertions, 22 deletions
diff --git a/common/log.cpp b/common/log.cpp index b0f6237..099c043 100644 --- a/common/log.cpp +++ b/common/log.cpp | |||
@@ -4,16 +4,25 @@ | |||
4 | #include <QIODevice> | 4 | #include <QIODevice> |
5 | #include <QCoreApplication> | 5 | #include <QCoreApplication> |
6 | #include <QSettings> | 6 | #include <QSettings> |
7 | #include <QStandardPaths> | ||
8 | #include <QSharedPointer> | 7 | #include <QSharedPointer> |
8 | #include <QMutex> | ||
9 | #include <QMutexLocker> | ||
9 | #include <iostream> | 10 | #include <iostream> |
10 | #include <unistd.h> | 11 | #include <unistd.h> |
12 | #include <memory> | ||
13 | #include <definitions.h> | ||
11 | 14 | ||
12 | using namespace Sink::Log; | 15 | using namespace Sink::Log; |
13 | 16 | ||
14 | static QSharedPointer<QSettings> config() | 17 | static QSharedPointer<QSettings> config() |
15 | { | 18 | { |
16 | return QSharedPointer<QSettings>::create(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sink/log.ini", QSettings::IniFormat); | 19 | return QSharedPointer<QSettings>::create(Sink::configLocation() + "/log.ini", QSettings::IniFormat); |
20 | } | ||
21 | |||
22 | static QByteArray sPrimaryComponent; | ||
23 | void Sink::Log::setPrimaryComponent(const QString &component) | ||
24 | { | ||
25 | sPrimaryComponent = component.toUtf8(); | ||
17 | } | 26 | } |
18 | 27 | ||
19 | class DebugStream : public QIODevice | 28 | class DebugStream : public QIODevice |
@@ -212,9 +221,63 @@ static QByteArray getProgramName() | |||
212 | } | 221 | } |
213 | } | 222 | } |
214 | 223 | ||
224 | static QSharedPointer<QSettings> debugAreasConfig() | ||
225 | { | ||
226 | return QSharedPointer<QSettings>::create(Sink::dataLocation() + "/debugAreas.ini", QSettings::IniFormat); | ||
227 | } | ||
228 | |||
229 | class DebugAreaCollector { | ||
230 | public: | ||
231 | DebugAreaCollector() | ||
232 | { | ||
233 | QMutexLocker locker(&mutex); | ||
234 | mDebugAreas = debugAreasConfig()->value("areas").value<QString>().split(';').toSet(); | ||
235 | } | ||
236 | |||
237 | ~DebugAreaCollector() | ||
238 | { | ||
239 | QMutexLocker locker(&mutex); | ||
240 | mDebugAreas += debugAreasConfig()->value("areas").value<QString>().split(';').toSet(); | ||
241 | debugAreasConfig()->setValue("areas", QVariant::fromValue(mDebugAreas.toList().join(';'))); | ||
242 | } | ||
243 | |||
244 | void add(const QString &area) | ||
245 | { | ||
246 | QMutexLocker locker(&mutex); | ||
247 | mDebugAreas << area; | ||
248 | } | ||
249 | |||
250 | QSet<QString> debugAreas() | ||
251 | { | ||
252 | QMutexLocker locker(&mutex); | ||
253 | return mDebugAreas; | ||
254 | } | ||
255 | |||
256 | QMutex mutex; | ||
257 | QSet<QString> mDebugAreas; | ||
258 | }; | ||
259 | |||
260 | static auto sDebugAreaCollector = std::unique_ptr<DebugAreaCollector>(new DebugAreaCollector); | ||
261 | |||
262 | QSet<QString> Sink::Log::debugAreas() | ||
263 | { | ||
264 | return sDebugAreaCollector->debugAreas(); | ||
265 | } | ||
266 | |||
267 | static void collectDebugArea(const QString &debugArea) | ||
268 | { | ||
269 | sDebugAreaCollector->add(debugArea); | ||
270 | } | ||
271 | |||
215 | static bool containsItemStartingWith(const QByteArray &pattern, const QByteArrayList &list) | 272 | static bool containsItemStartingWith(const QByteArray &pattern, const QByteArrayList &list) |
216 | { | 273 | { |
217 | for (const auto &item : list) { | 274 | for (const auto &item : list) { |
275 | if (item.startsWith('*')) { | ||
276 | auto stripped = item.mid(1); | ||
277 | if (pattern.contains(stripped)) { | ||
278 | return true; | ||
279 | } | ||
280 | } | ||
218 | if (pattern.startsWith(item)) { | 281 | if (pattern.startsWith(item)) { |
219 | return true; | 282 | return true; |
220 | } | 283 | } |
@@ -232,24 +295,23 @@ static bool caseInsensitiveContains(const QByteArray &pattern, const QByteArrayL | |||
232 | return false; | 295 | return false; |
233 | } | 296 | } |
234 | 297 | ||
235 | QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file, const char *function, const char *debugArea) | 298 | QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file, const char *function, const char *debugArea, const char *debugComponent) |
236 | { | 299 | { |
237 | static NullStream nullstream; | 300 | static NullStream nullstream; |
238 | if (debugLevel < debugOutputLevel()) { | 301 | if (debugLevel < debugOutputLevel()) { |
239 | return QDebug(&nullstream); | 302 | return QDebug(&nullstream); |
240 | } | 303 | } |
241 | 304 | ||
242 | auto areas = debugOutputFilter(Sink::Log::Area); | 305 | if (sPrimaryComponent.isEmpty()) { |
243 | if (debugArea && !areas.isEmpty()) { | 306 | sPrimaryComponent = getProgramName(); |
244 | if (!containsItemStartingWith(debugArea, areas)) { | ||
245 | return QDebug(&nullstream); | ||
246 | } | ||
247 | } | 307 | } |
248 | static QByteArray programName = getProgramName(); | 308 | QString fullDebugArea = sPrimaryComponent + "." + (debugComponent ? (QString::fromLatin1(debugComponent) + ".") : "") + (debugArea ? QString::fromLatin1(debugArea) : ""); |
309 | |||
310 | collectDebugArea(fullDebugArea); | ||
249 | 311 | ||
250 | auto filter = debugOutputFilter(Sink::Log::ApplicationName); | 312 | auto areas = debugOutputFilter(Sink::Log::Area); |
251 | if (!filter.isEmpty() && !filter.contains(programName)) { | 313 | if (!areas.isEmpty()) { |
252 | if (!containsItemStartingWith(programName, filter)) { | 314 | if (!containsItemStartingWith(fullDebugArea.toUtf8(), areas)) { |
253 | return QDebug(&nullstream); | 315 | return QDebug(&nullstream); |
254 | } | 316 | } |
255 | } | 317 | } |
@@ -293,19 +355,17 @@ QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file, | |||
293 | } | 355 | } |
294 | if (showProgram) { | 356 | if (showProgram) { |
295 | int width = 10; | 357 | int width = 10; |
296 | output += QString(" %1(%2)").arg(QString::fromLatin1(programName).leftJustified(width, ' ', true)).arg(unsigned(getpid())).rightJustified(width + 8, ' '); | 358 | output += QString(" %1(%2)").arg(QString::fromLatin1(getProgramName()).leftJustified(width, ' ', true)).arg(unsigned(getpid())).rightJustified(width + 8, ' '); |
297 | } | 359 | } |
298 | if (debugArea) { | 360 | if (useColor) { |
299 | if (useColor) { | 361 | output += colorCommand(QList<int>() << ANSI_Colors::Bold << prefixColorCode); |
300 | output += colorCommand(QList<int>() << ANSI_Colors::Bold << prefixColorCode); | 362 | } |
301 | } | 363 | output += QString(" %1 ").arg(fullDebugArea.leftJustified(25, ' ', true)); |
302 | output += QString(" %1 ").arg(QString::fromLatin1(debugArea).leftJustified(25, ' ', true)); | 364 | if (useColor) { |
303 | if (useColor) { | 365 | output += resetColor; |
304 | output += resetColor; | ||
305 | } | ||
306 | } | 366 | } |
307 | if (showFunction) { | 367 | if (showFunction) { |
308 | output += QString(" %3").arg(QString::fromLatin1(function).leftJustified(25, ' ', true)); | 368 | output += QString(" %3").arg(fullDebugArea.leftJustified(25, ' ', true)); |
309 | } | 369 | } |
310 | if (showLocation) { | 370 | if (showLocation) { |
311 | const auto filename = QString::fromLatin1(file).split('/').last(); | 371 | const auto filename = QString::fromLatin1(file).split('/').last(); |