summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2018-01-03 15:41:02 +0100
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2018-01-12 11:50:36 +0000
commit114f7952217c9cbe7d0054bdcbef775a5923e4a0 (patch)
tree10f5e0099b8004ef12eed496c640cd347b162931
parent84e7b6409042b269c89dff2187f563027e379ec0 (diff)
logging: Break out alternative logging sinks into a well defined API
First steps towards a public API for having multiple output sinks is to allow this internally. We give all the different log sinks the same signature, with a bool return value to signify if stderr has been handled. The logic of not logging to the alternative sinks when the function qt_logging_to_console() returns true has been moved into each sink, so that they in the future may choose to log even when also logging to the console, allowing multi-sink output. They must then make sure to return true if the native logging sink has also logged to stderr. The logic of each sink has been kept the same when it comes to the formatting of the message. Some of these sinks should ideally use the raw message instead of the formatted one, as they are structured logging sinks. Change-Id: I441d3bc1db3e16180704e00d13a40564b6f06a6c Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Simon Hausmann <simon.hausmann@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
-rw-r--r--src/corelib/global/qlogging.cpp104
1 files changed, 74 insertions, 30 deletions
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 2bacdbb77c..54064f6c1c 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1317,8 +1317,13 @@ static QString formatBacktraceForLogMessage(const QMessagePattern::BacktracePara
#define QT_LOG_CODE 9000
#endif
-static void slog2_default_handler(QtMsgType msgType, const char *message)
+static bool slog2_default_handler(QtMsgType type, const QMessageLogContext &context, const QString &message)
{
+ if (!qt_logging_to_console())
+ return false;
+
+ QString formattedMessage = qFormatLogMessage(type, context, message);
+ formattedMessage.append(QLatin1Char('\n'));
if (slog2_set_default_buffer((slog2_buffer_t)-1) == 0) {
slog2_buffer_set_config_t buffer_config;
slog2_buffer_t buffer_handle;
@@ -1331,7 +1336,7 @@ static void slog2_default_handler(QtMsgType msgType, const char *message)
if (slog2_register(&buffer_config, &buffer_handle, 0) == -1) {
fprintf(stderr, "Error registering slogger2 buffer!\n");
- fprintf(stderr, "%s", message);
+ fprintf(stderr, "%s", formattedMessage.toLocal8Bit().constData());
fflush(stderr);
return;
}
@@ -1359,7 +1364,9 @@ static void slog2_default_handler(QtMsgType msgType, const char *message)
break;
}
//writes to the slog2 buffer
- slog2c(NULL, QT_LOG_CODE, severity, message);
+ slog2c(NULL, QT_LOG_CODE, severity, formattedMessage.toLocal8Bit().constData());
+
+ return false;
}
#endif // slog2
@@ -1513,10 +1520,15 @@ static QBasicAtomicPointer<void (QtMsgType, const char*)> msgHandler = Q_BASIC_A
static QBasicAtomicPointer<void (QtMsgType, const QMessageLogContext &, const QString &)> messageHandler = Q_BASIC_ATOMIC_INITIALIZER(qDefaultMessageHandler);
#if QT_CONFIG(journald)
-static void systemd_default_message_handler(QtMsgType type,
+static bool systemd_default_message_handler(QtMsgType type,
const QMessageLogContext &context,
const QString &message)
{
+ if (qt_logging_to_console())
+ return false;
+
+ QString formattedMessage = qFormatLogMessage(type, context, message);
+
int priority = LOG_INFO; // Informational
switch (type) {
case QtDebugMsg:
@@ -1536,19 +1548,26 @@ static void systemd_default_message_handler(QtMsgType type,
break;
}
- sd_journal_send("MESSAGE=%s", message.toUtf8().constData(),
+ sd_journal_send("MESSAGE=%s", formattedMessage.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);
+
+ return false;
}
#endif
#if QT_CONFIG(syslog)
-static void syslog_default_message_handler(QtMsgType type, const char *message)
+static bool syslog_default_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message)
{
+ if (qt_logging_to_console())
+ return false;
+
+ QString formattedMessage = qFormatLogMessage(type, context, message);
+
int priority = LOG_INFO; // Informational
switch (type) {
case QtDebugMsg:
@@ -1568,15 +1587,22 @@ static void syslog_default_message_handler(QtMsgType type, const char *message)
break;
}
- syslog(priority, "%s", message);
+ syslog(priority, "%s", formattedMessage.toUtf8().constData());
+
+ return false;
}
#endif
#ifdef Q_OS_ANDROID
-static void android_default_message_handler(QtMsgType type,
+static bool android_default_message_handler(QtMsgType type,
const QMessageLogContext &context,
const QString &message)
{
+ if (qt_logging_to_console())
+ return false;
+
+ QString formattedMessage = qFormatLogMessage(type, context, message);
+
android_LogPriority priority = ANDROID_LOG_DEBUG;
switch (type) {
case QtDebugMsg: priority = ANDROID_LOG_DEBUG; break;
@@ -1588,44 +1614,62 @@ static void android_default_message_handler(QtMsgType type,
__android_log_print(priority, qPrintable(QCoreApplication::applicationName()),
"%s:%d (%s): %s\n", context.file, context.line,
- context.function, qPrintable(message));
+ context.function, qPrintable(formattedMessage));
+
+ return false;
}
#endif //Q_OS_ANDROID
+#ifdef Q_OS_WIN
+static bool win_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message)
+{
+ if (qt_logging_to_console())
+ return false;
+
+ QString formattedMessage = qFormatLogMessage(type, context, message);
+ formattedMessage.append(QLatin1Char('\n'));
+ OutputDebugString(reinterpret_cast<const wchar_t *>(formattedMessage.utf16()));
+ return false;
+}
+#endif
+
/*!
\internal
*/
static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context,
- const QString &buf)
+ const QString &message)
{
- QString logMessage = qFormatLogMessage(type, context, buf);
+ bool handledStderr = false;
- // print nothing if message pattern didn't apply / was empty.
- // (still print empty lines, e.g. because message itself was empty)
- if (logMessage.isNull())
- return;
+ // A message sink logs the message to a structured or unstructured destination,
+ // optionally formatting the message if the latter, and returns true if the sink
+ // handled stderr output as well, which will shortcut our default stderr output.
+ // In the future, if we allow multiple/dynamic sinks, this will be iterating
+ // a list of sinks.
- if (!qt_logging_to_console()) {
#if defined(Q_OS_WIN)
- logMessage.append(QLatin1Char('\n'));
- OutputDebugString(reinterpret_cast<const wchar_t *>(logMessage.utf16()));
- return;
+ handledStderr |= win_message_handler(type, context, message);
#elif QT_CONFIG(slog2)
- logMessage.append(QLatin1Char('\n'));
- slog2_default_handler(type, logMessage.toLocal8Bit().constData());
- return;
+ handledStderr |= slog2_default_handler(type, context, message);
#elif QT_CONFIG(journald)
- systemd_default_message_handler(type, context, logMessage);
- return;
+ handledStderr |= systemd_default_message_handler(type, context, message);
#elif QT_CONFIG(syslog)
- syslog_default_message_handler(type, logMessage.toUtf8().constData());
- return;
+ handledStderr |= syslog_default_message_handler(type, context, message);
#elif defined(Q_OS_ANDROID)
- android_default_message_handler(type, context, logMessage);
- return;
+ handledStderr |= android_default_message_handler(type, context, message);
#endif
- }
- fprintf(stderr, "%s\n", logMessage.toLocal8Bit().constData());
+
+ if (handledStderr || !qt_logging_to_console())
+ return;
+
+ QString formattedMessage = qFormatLogMessage(type, context, message);
+
+ // print nothing if message pattern didn't apply / was empty.
+ // (still print empty lines, e.g. because message itself was empty)
+ if (formattedMessage.isNull())
+ return;
+
+ fprintf(stderr, "%s\n", formattedMessage.toLocal8Bit().constData());
fflush(stderr);
}