summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qlogging.cpp
diff options
context:
space:
mode:
authorKai Köhne <kai.koehne@qt.io>2025-05-11 15:06:36 +0200
committerThiago Macieira <thiago.macieira@intel.com>2025-05-19 18:50:25 +0000
commita6070847f075296458e1afef0210f9c89aca4b2a (patch)
treee7289a608f94dcb50c6a1d797ce9dfef8ba1ba77 /src/corelib/global/qlogging.cpp
parent927798f5deb0bd95fc8ce5be9fb0cfceef94a46b (diff)
qlogging: Journal: Log thread id, suppress empty fields
The TID field can be used to differentiate the threads of a process where the message originates from. This allows to create a timeline of events when identical messages are created from multiple threads, or filter out messages from "uninteresting" threads in post-processing. The file/line/func fields are typically empty for non-debug builds, so storing these in the journal with dummy values is a waste of CPU time and storage. Use sd_journal_sendv instead of sd_journal_send, as that allows to vary the number of sent fields, and skip the ones without actual information. It is also slightly more performant, as it avoids the var-arg handling, sprintf parsing and formatting etc. done by sd_journal_send. [ChangeLog][QtCore][Logging] Qt now logs the thread id (TID) in journal, allowing separation of identical messages from multiple threads. Fixes: QTBUG-120047 Fixes: QTBUG-120048 Change-Id: Iccf3fe708dc4b896161693e13fb9012686bd1871 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/global/qlogging.cpp')
-rw-r--r--src/corelib/global/qlogging.cpp40
1 files changed, 33 insertions, 7 deletions
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 26d50af3a30..170ccfa7ebf 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1846,13 +1846,39 @@ static bool systemd_default_message_handler(QtMsgType type,
break;
}
- sd_journal_send("MESSAGE=%s", message.toUtf8().constData(),
- "PRIORITY=%i", priority,
- "CODE_FUNC=%s", context.function ? context.function : "unknown",
- "CODE_LINE=%d", context.line,
- "CODE_FILE=%s", context.file ? context.file : "unknown",
- "QT_CATEGORY=%s", context.category ? context.category : "unknown",
- NULL);
+ // Explicit QByteArray instead of auto, to resolve the QStringBuilder proxy
+ const QByteArray messageField = "MESSAGE="_ba + message.toUtf8().constData();
+ const QByteArray priorityField = "PRIORITY="_ba + QByteArray::number(priority);
+ const QByteArray tidField = "TID="_ba + QByteArray::number(qlonglong(qt_gettid()));
+ const QByteArray fileField = context.file
+ ? "CODE_FILE="_ba + context.file : QByteArray();
+ const QByteArray funcField = context.function
+ ? "CODE_FUNC="_ba + context.function : QByteArray();
+ const QByteArray lineField = context.line
+ ? "CODE_LINE="_ba + QByteArray::number(context.line) : QByteArray();
+ const QByteArray categoryField = context.category
+ ? "QT_CATEGORY="_ba + context.category : QByteArray();
+
+ auto toIovec = [](const QByteArray &ba) {
+ return iovec{const_cast<char*>(ba.data()), ba.size()};
+ };
+
+ struct iovec fields[7] = {
+ toIovec(messageField),
+ toIovec(priorityField),
+ toIovec(tidField),
+ };
+ int nFields = 3;
+ if (context.file)
+ fields[nFields++] = toIovec(fileField);
+ if (context.function)
+ fields[nFields++] = toIovec(funcField);
+ if (context.line)
+ fields[nFields++] = toIovec(lineField);
+ if (context.category)
+ fields[nFields++] = toIovec(categoryField);
+
+ sd_journal_sendv(fields, nFields);
return true; // Prevent further output to stderr
}