diff options
| author | Kai Köhne <kai.koehne@qt.io> | 2025-05-11 15:06:36 +0200 |
|---|---|---|
| committer | Thiago Macieira <thiago.macieira@intel.com> | 2025-05-19 18:50:25 +0000 |
| commit | a6070847f075296458e1afef0210f9c89aca4b2a (patch) | |
| tree | e7289a608f94dcb50c6a1d797ce9dfef8ba1ba77 /src/corelib/global/qlogging.cpp | |
| parent | 927798f5deb0bd95fc8ce5be9fb0cfceef94a46b (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.cpp | 40 |
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 } |
