summaryrefslogtreecommitdiffstats
path: root/common/log.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/log.cpp')
-rw-r--r--common/log.cpp87
1 files changed, 61 insertions, 26 deletions
diff --git a/common/log.cpp b/common/log.cpp
index 045b3cc..5dfb872 100644
--- a/common/log.cpp
+++ b/common/log.cpp
@@ -1,6 +1,7 @@
1#include "log.h" 1#include "log.h"
2 2
3#include <QString> 3#include <QString>
4#include <QDir>
4#include <QIODevice> 5#include <QIODevice>
5#include <QCoreApplication> 6#include <QCoreApplication>
6#include <QSettings> 7#include <QSettings>
@@ -12,12 +13,18 @@
12#include <memory> 13#include <memory>
13#include <atomic> 14#include <atomic>
14#include <definitions.h> 15#include <definitions.h>
16#include <QThreadStorage>
17#include <QStringBuilder>
15 18
16using namespace Sink::Log; 19using namespace Sink::Log;
17 20
18static QSharedPointer<QSettings> config() 21static QThreadStorage<QSharedPointer<QSettings>> sSettings;
22static QSettings &config()
19{ 23{
20 return QSharedPointer<QSettings>::create(Sink::configLocation() + "/log.ini", QSettings::IniFormat); 24 if (!sSettings.hasLocalData()) {
25 sSettings.setLocalData(QSharedPointer<QSettings>::create(Sink::configLocation() + "/log.ini", QSettings::IniFormat));
26 }
27 return *sSettings.localData();
21} 28}
22 29
23static QByteArray sPrimaryComponent; 30static QByteArray sPrimaryComponent;
@@ -173,22 +180,22 @@ DebugLevel Sink::Log::debugLevelFromName(const QByteArray &name)
173 180
174void Sink::Log::setDebugOutputLevel(DebugLevel debugLevel) 181void Sink::Log::setDebugOutputLevel(DebugLevel debugLevel)
175{ 182{
176 config()->setValue("level", debugLevel); 183 config().setValue("level", debugLevel);
177} 184}
178 185
179Sink::Log::DebugLevel Sink::Log::debugOutputLevel() 186Sink::Log::DebugLevel Sink::Log::debugOutputLevel()
180{ 187{
181 return static_cast<Sink::Log::DebugLevel>(config()->value("level", Sink::Log::Log).toInt()); 188 return static_cast<Sink::Log::DebugLevel>(config().value("level", Sink::Log::Log).toInt());
182} 189}
183 190
184void Sink::Log::setDebugOutputFilter(FilterType type, const QByteArrayList &filter) 191void Sink::Log::setDebugOutputFilter(FilterType type, const QByteArrayList &filter)
185{ 192{
186 switch (type) { 193 switch (type) {
187 case ApplicationName: 194 case ApplicationName:
188 config()->setValue("applicationfilter", QVariant::fromValue(filter)); 195 config().setValue("applicationfilter", QVariant::fromValue(filter));
189 break; 196 break;
190 case Area: 197 case Area:
191 config()->setValue("areafilter", QVariant::fromValue(filter)); 198 config().setValue("areafilter", QVariant::fromValue(filter));
192 break; 199 break;
193 } 200 }
194} 201}
@@ -197,9 +204,9 @@ QByteArrayList Sink::Log::debugOutputFilter(FilterType type)
197{ 204{
198 switch (type) { 205 switch (type) {
199 case ApplicationName: 206 case ApplicationName:
200 return config()->value("applicationfilter").value<QByteArrayList>(); 207 return config().value("applicationfilter").value<QByteArrayList>();
201 case Area: 208 case Area:
202 return config()->value("areafilter").value<QByteArrayList>(); 209 return config().value("areafilter").value<QByteArrayList>();
203 default: 210 default:
204 return QByteArrayList(); 211 return QByteArrayList();
205 } 212 }
@@ -207,12 +214,12 @@ QByteArrayList Sink::Log::debugOutputFilter(FilterType type)
207 214
208void Sink::Log::setDebugOutputFields(const QByteArrayList &output) 215void Sink::Log::setDebugOutputFields(const QByteArrayList &output)
209{ 216{
210 config()->setValue("outputfields", QVariant::fromValue(output)); 217 config().setValue("outputfields", QVariant::fromValue(output));
211} 218}
212 219
213QByteArrayList Sink::Log::debugOutputFields() 220QByteArrayList Sink::Log::debugOutputFields()
214{ 221{
215 return config()->value("outputfields").value<QByteArrayList>(); 222 return config().value("outputfields").value<QByteArrayList>();
216} 223}
217 224
218static QByteArray getProgramName() 225static QByteArray getProgramName()
@@ -277,14 +284,16 @@ static bool containsItemStartingWith(const QByteArray &pattern, const QByteArray
277 for (const auto &item : list) { 284 for (const auto &item : list) {
278 if (item.startsWith('*')) { 285 if (item.startsWith('*')) {
279 auto stripped = item.mid(1); 286 auto stripped = item.mid(1);
280 stripped.endsWith('*'); 287 if (stripped.endsWith('*')) {
281 stripped.chop(1); 288 stripped.chop(1);
289 }
282 if (pattern.contains(stripped)) { 290 if (pattern.contains(stripped)) {
283 return true; 291 return true;
284 } 292 }
285 } 293 } else {
286 if (pattern.startsWith(item)) { 294 if (pattern.contains(item)) {
287 return true; 295 return true;
296 }
288 } 297 }
289 } 298 }
290 return false; 299 return false;
@@ -300,25 +309,51 @@ static bool caseInsensitiveContains(const QByteArray &pattern, const QByteArrayL
300 return false; 309 return false;
301} 310}
302 311
303QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file, const char *function, const char *debugArea, const char *debugComponent) 312static QByteArray getFileName(const char *file)
304{ 313{
305 static NullStream nullstream; 314 static char sep = QDir::separator().toLatin1();
306 if (debugLevel < debugOutputLevel()) { 315 auto filename = QByteArray(file).split(sep).last();
307 return QDebug(&nullstream); 316 return filename.split('.').first();
308 } 317}
309 318
319static QString assembleDebugArea(const char *debugArea, const char *debugComponent, const char *file)
320{
310 if (sPrimaryComponent.isEmpty()) { 321 if (sPrimaryComponent.isEmpty()) {
311 sPrimaryComponent = getProgramName(); 322 sPrimaryComponent = getProgramName();
312 } 323 }
313 QString fullDebugArea = sPrimaryComponent + "." + (debugComponent ? (QString::fromLatin1(debugComponent) + ".") : "") + (debugArea ? QString::fromLatin1(debugArea) : ""); 324 //Using stringbuilder for fewer allocations
325 return QLatin1String{sPrimaryComponent} % QLatin1String{"."} %
326 (debugComponent ? (QLatin1String{debugComponent} + QLatin1String{"."}) : QLatin1String{""}) %
327 (debugArea ? QLatin1String{debugArea} : QLatin1String{getFileName(file)});
328}
329
330static bool isFiltered(DebugLevel debugLevel, const QByteArray &fullDebugArea)
331{
332 if (debugLevel < debugOutputLevel()) {
333 return true;
334 }
335 const auto areas = debugOutputFilter(Sink::Log::Area);
336 if ((debugLevel <= Sink::Log::Trace) && !areas.isEmpty()) {
337 if (!containsItemStartingWith(fullDebugArea, areas)) {
338 return true;
339 }
340 }
341 return false;
342}
314 343
344bool Sink::Log::isFiltered(DebugLevel debugLevel, const char *debugArea, const char *debugComponent, const char *file)
345{
346 return isFiltered(debugLevel, assembleDebugArea(debugArea, debugComponent, file).toLatin1());
347}
348
349QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file, const char *function, const char *debugArea, const char *debugComponent)
350{
351 const auto fullDebugArea = assembleDebugArea(debugArea, debugComponent, file);
315 collectDebugArea(fullDebugArea); 352 collectDebugArea(fullDebugArea);
316 353
317 auto areas = debugOutputFilter(Sink::Log::Area); 354 static NullStream nullstream;
318 if (debugLevel <= Sink::Log::Trace && !areas.isEmpty()) { 355 if (isFiltered(debugLevel, fullDebugArea.toLatin1())) {
319 if (!containsItemStartingWith(fullDebugArea.toUtf8(), areas)) { 356 return QDebug(&nullstream);
320 return QDebug(&nullstream);
321 }
322 } 357 }
323 358
324 QString prefix; 359 QString prefix;