diff options
Diffstat (limited to 'common/log.cpp')
-rw-r--r-- | common/log.cpp | 87 |
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 | ||
16 | using namespace Sink::Log; | 19 | using namespace Sink::Log; |
17 | 20 | ||
18 | static QSharedPointer<QSettings> config() | 21 | static QThreadStorage<QSharedPointer<QSettings>> sSettings; |
22 | static 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 | ||
23 | static QByteArray sPrimaryComponent; | 30 | static QByteArray sPrimaryComponent; |
@@ -173,22 +180,22 @@ DebugLevel Sink::Log::debugLevelFromName(const QByteArray &name) | |||
173 | 180 | ||
174 | void Sink::Log::setDebugOutputLevel(DebugLevel debugLevel) | 181 | void Sink::Log::setDebugOutputLevel(DebugLevel debugLevel) |
175 | { | 182 | { |
176 | config()->setValue("level", debugLevel); | 183 | config().setValue("level", debugLevel); |
177 | } | 184 | } |
178 | 185 | ||
179 | Sink::Log::DebugLevel Sink::Log::debugOutputLevel() | 186 | Sink::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 | ||
184 | void Sink::Log::setDebugOutputFilter(FilterType type, const QByteArrayList &filter) | 191 | void 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 | ||
208 | void Sink::Log::setDebugOutputFields(const QByteArrayList &output) | 215 | void 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 | ||
213 | QByteArrayList Sink::Log::debugOutputFields() | 220 | QByteArrayList Sink::Log::debugOutputFields() |
214 | { | 221 | { |
215 | return config()->value("outputfields").value<QByteArrayList>(); | 222 | return config().value("outputfields").value<QByteArrayList>(); |
216 | } | 223 | } |
217 | 224 | ||
218 | static QByteArray getProgramName() | 225 | static 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 | ||
303 | QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file, const char *function, const char *debugArea, const char *debugComponent) | 312 | static 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 | ||
319 | static 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 | |||
330 | static 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 | ||
344 | bool 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 | |||
349 | QDebug 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; |