summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qlogging.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/global/qlogging.cpp')
-rw-r--r--src/corelib/global/qlogging.cpp323
1 files changed, 321 insertions, 2 deletions
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 28493311fb..dbe28da120 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -46,10 +46,10 @@
#include "qvarlengtharray.h"
#include "qdebug.h"
#include "qmutex.h"
+#include "qloggingcategory.h"
#ifndef QT_BOOTSTRAPPED
#include "qcoreapplication.h"
#include "qthread.h"
-#include "qloggingcategory.h"
#include "private/qloggingregistry_p.h"
#endif
#ifdef Q_OS_WIN
@@ -63,6 +63,11 @@
#include <android/log.h>
#endif
+#if defined(QT_USE_JOURNALD) && !defined(QT_BOOTSTRAPPED)
+# include <systemd/sd-journal.h>
+# include <unistd.h>
+#endif
+
#include <stdio.h>
QT_BEGIN_NAMESPACE
@@ -265,6 +270,74 @@ void QMessageLogger::debug(const char *msg, ...) const
qt_message_fatal(QtDebugMsg, context, message);
}
+/*!
+ \typedef QMessageLogger::CategoryFunction
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+
+ \snippet code/qlogging/qlogging.cpp 2
+
+ A function which this signature is generated by Q_DECLARE_LOGGING_CATEGORY,
+ Q_LOGGING_CATEGORY.
+
+ \since 5.3
+*/
+
+/*!
+ Logs a debug message specified with format \a msg for the context \a cat.
+ Additional parameters, specified by \a msg, may be used.
+
+ \since 5.3
+ \sa qCDebug()
+*/
+void QMessageLogger::debug(const QLoggingCategory &cat, const char *msg, ...) const
+{
+ if (!cat.isDebugEnabled())
+ return;
+
+ QMessageLogContext ctxt;
+ ctxt.copy(context);
+ ctxt.category = cat.categoryName();
+
+ QString message;
+
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ qt_message(QtDebugMsg, ctxt, msg, ap, message);
+ va_end(ap);
+
+ if (isFatal(QtDebugMsg))
+ qt_message_fatal(QtDebugMsg, ctxt, message);
+}
+
+/*!
+ Logs a debug message specified with format \a msg for the context returned
+ by \a catFunc. Additional parameters, specified by \a msg, may be used.
+
+ \since 5.3
+ \sa qCDebug()
+*/
+void QMessageLogger::debug(QMessageLogger::CategoryFunction catFunc,
+ const char *msg, ...) const
+{
+ const QLoggingCategory &cat = (*catFunc)();
+
+ QMessageLogContext ctxt;
+ ctxt.copy(context);
+ ctxt.category = cat.categoryName();
+
+ QString message;
+
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ qt_message(QtDebugMsg, ctxt, msg, ap, message);
+ va_end(ap);
+
+ if (isFatal(QtDebugMsg))
+ qt_message_fatal(QtDebugMsg, ctxt, message);
+}
+
#ifndef QT_NO_DEBUG_STREAM
/*!
@@ -281,6 +354,36 @@ QDebug QMessageLogger::debug() const
}
/*!
+ Logs a debug message into category \a cat using a QDebug stream.
+
+ \since 5.3
+ \sa qCDebug(), QDebug
+*/
+QDebug QMessageLogger::debug(const QLoggingCategory &cat) const
+{
+ QDebug dbg = QDebug(QtDebugMsg);
+ if (!cat.isDebugEnabled())
+ dbg.stream->message_output = false;
+
+ QMessageLogContext &ctxt = dbg.stream->context;
+ ctxt.copy(context);
+ ctxt.category = cat.categoryName();
+
+ return dbg;
+}
+
+/*!
+ Logs a debug message into category returned by \a catFunc using a QDebug stream.
+
+ \since 5.3
+ \sa qCDebug(), QDebug
+*/
+QDebug QMessageLogger::debug(QMessageLogger::CategoryFunction catFunc) const
+{
+ return debug((*catFunc)());
+}
+
+/*!
\internal
Returns a QNoDebug object, which is used to ignore debugging output.
@@ -314,9 +417,65 @@ void QMessageLogger::warning(const char *msg, ...) const
qt_message_fatal(QtWarningMsg, context, message);
}
+/*!
+ Logs a warning message specified with format \a msg for the context \a cat.
+ Additional parameters, specified by \a msg, may be used.
+
+ \since 5.3
+ \sa qCWarning()
+*/
+void QMessageLogger::warning(const QLoggingCategory &cat, const char *msg, ...) const
+{
+ if (!cat.isWarningEnabled())
+ return;
+
+ QMessageLogContext ctxt;
+ ctxt.copy(context);
+ ctxt.category = cat.categoryName();
+
+ QString message;
+
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ qt_message(QtWarningMsg, ctxt, msg, ap, message);
+ va_end(ap);
+
+ if (isFatal(QtWarningMsg))
+ qt_message_fatal(QtWarningMsg, ctxt, message);
+}
+
+/*!
+ Logs a warning message specified with format \a msg for the context returned
+ by \a catFunc. Additional parameters, specified by \a msg, may be used.
+
+ \since 5.3
+ \sa qCWarning()
+*/
+void QMessageLogger::warning(QMessageLogger::CategoryFunction catFunc,
+ const char *msg, ...) const
+{
+ const QLoggingCategory &cat = (*catFunc)();
+ if (!cat.isWarningEnabled())
+ return;
+
+ QMessageLogContext ctxt;
+ ctxt.copy(context);
+ ctxt.category = cat.categoryName();
+
+ QString message;
+
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ qt_message(QtWarningMsg, ctxt, msg, ap, message);
+ va_end(ap);
+
+ if (isFatal(QtWarningMsg))
+ qt_message_fatal(QtWarningMsg, ctxt, message);
+}
+
#ifndef QT_NO_DEBUG_STREAM
/*!
- Logs a debug message using a QDebug stream
+ Logs a warning message using a QDebug stream
\sa qWarning(), QDebug
*/
@@ -327,6 +486,36 @@ QDebug QMessageLogger::warning() const
ctxt.copy(context);
return dbg;
}
+
+/*!
+ Logs a warning message into category \a cat using a QDebug stream.
+
+ \sa qCWarning(), QDebug
+*/
+QDebug QMessageLogger::warning(const QLoggingCategory &cat) const
+{
+ QDebug dbg = QDebug(QtWarningMsg);
+ if (!cat.isWarningEnabled())
+ dbg.stream->message_output = false;
+
+ QMessageLogContext &ctxt = dbg.stream->context;
+ ctxt.copy(context);
+ ctxt.category = cat.categoryName();
+
+ return dbg;
+}
+
+/*!
+ Logs a warning message into category returned by \a catFunc using a QDebug stream.
+
+ \since 5.3
+ \sa qCWarning(), QDebug
+*/
+QDebug QMessageLogger::warning(QMessageLogger::CategoryFunction catFunc) const
+{
+ return warning((*catFunc)());
+}
+
#endif
#undef qCritical
@@ -350,6 +539,62 @@ void QMessageLogger::critical(const char *msg, ...) const
qt_message_fatal(QtCriticalMsg, context, message);
}
+/*!
+ Logs a critical message specified with format \a msg for the context \a cat.
+ Additional parameters, specified by \a msg, may be used.
+
+ \since 5.3
+ \sa qCCritical()
+*/
+void QMessageLogger::critical(const QLoggingCategory &cat, const char *msg, ...) const
+{
+ if (!cat.isCriticalEnabled())
+ return;
+
+ QMessageLogContext ctxt;
+ ctxt.copy(context);
+ ctxt.category = cat.categoryName();
+
+ QString message;
+
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ qt_message(QtCriticalMsg, ctxt, msg, ap, message);
+ va_end(ap);
+
+ if (isFatal(QtCriticalMsg))
+ qt_message_fatal(QtCriticalMsg, ctxt, message);
+}
+
+/*!
+ Logs a critical message specified with format \a msg for the context returned
+ by \a catFunc. Additional parameters, specified by \a msg, may be used.
+
+ \since 5.3
+ \sa qCCritical()
+*/
+void QMessageLogger::critical(QMessageLogger::CategoryFunction catFunc,
+ const char *msg, ...) const
+{
+ const QLoggingCategory &cat = (*catFunc)();
+ if (!cat.isCriticalEnabled())
+ return;
+
+ QMessageLogContext ctxt;
+ ctxt.copy(context);
+ ctxt.category = cat.categoryName();
+
+ QString message;
+
+ va_list ap;
+ va_start(ap, msg); // use variable arg list
+ qt_message(QtCriticalMsg, ctxt, msg, ap, message);
+ va_end(ap);
+
+ if (isFatal(QtCriticalMsg))
+ qt_message_fatal(QtCriticalMsg, ctxt, message);
+}
+
#ifndef QT_NO_DEBUG_STREAM
/*!
Logs a critical message using a QDebug stream
@@ -363,6 +608,37 @@ QDebug QMessageLogger::critical() const
ctxt.copy(context);
return dbg;
}
+
+/*!
+ Logs a critical message into category \a cat using a QDebug stream.
+
+ \since 5.3
+ \sa qCCritical(), QDebug
+*/
+QDebug QMessageLogger::critical(const QLoggingCategory &cat) const
+{
+ QDebug dbg = QDebug(QtCriticalMsg);
+ if (!cat.isCriticalEnabled())
+ dbg.stream->message_output = false;
+
+ QMessageLogContext &ctxt = dbg.stream->context;
+ ctxt.copy(context);
+ ctxt.category = cat.categoryName();
+
+ return dbg;
+}
+
+/*!
+ Logs a critical message into category returned by \a catFunc using a QDebug stream.
+
+ \since 5.3
+ \sa qCCritical(), QDebug
+*/
+QDebug QMessageLogger::critical(QMessageLogger::CategoryFunction catFunc) const
+{
+ return critical((*catFunc)());
+}
+
#endif
#undef qFatal
@@ -866,6 +1142,37 @@ Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler);
static QtMsgHandler msgHandler = 0; // pointer to debug handler (without context)
static QtMessageHandler messageHandler = 0; // pointer to debug handler (with context)
+#if defined(QT_USE_JOURNALD) && !defined(QT_BOOTSTRAPPED)
+static void systemd_default_message_handler(QtMsgType type,
+ const QMessageLogContext &context,
+ const QString &message)
+{
+ int priority = LOG_INFO; // Informational
+ switch (type) {
+ case QtDebugMsg:
+ priority = LOG_DEBUG; // Debug-level messages
+ break;
+ case QtWarningMsg:
+ priority = LOG_WARNING; // Warning conditions
+ break;
+ case QtCriticalMsg:
+ priority = LOG_CRIT; // Critical conditions
+ break;
+ case QtFatalMsg:
+ priority = LOG_ALERT; // Action must be taken immediately
+ break;
+ }
+
+ char filebuf[PATH_MAX + sizeof("CODE_FILE=")];
+ snprintf(filebuf, sizeof(filebuf), "CODE_FILE=%s", context.file ? context.file : "unknown");
+
+ char linebuf[20];
+ snprintf(linebuf, sizeof(linebuf), "CODE_LINE=%d", context.line);
+
+ sd_journal_print_with_location(priority, filebuf, linebuf, context.function ? context.function : "unknown", "%s", message.toUtf8().constData());
+}
+#endif
+
#ifdef Q_OS_ANDROID
static void android_default_message_handler(QtMsgType type,
const QMessageLogContext &context,
@@ -902,6 +1209,18 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con
#if defined(QT_USE_SLOG2)
slog2_default_handler(type, logMessage.toLocal8Bit().constData());
+#elif defined(QT_USE_JOURNALD) && !defined(QT_BOOTSTRAPPED)
+ // We use isatty to catch the obvious case of someone running something interactively.
+ // We also support an environment variable for Qt Creator use, or more complicated cases like subprocesses.
+ static bool logToConsole = isatty(fileno(stdin)) || !qEnvironmentVariableIsEmpty("QT_NO_JOURNALD_LOG");
+ if (Q_LIKELY(!logToConsole)) {
+ // remove trailing \n, systemd appears to want them newline-less
+ logMessage.chop(1);
+ systemd_default_message_handler(type, context, logMessage);
+ } else {
+ fprintf(stderr, "%s", logMessage.toUtf8().constData());
+ fflush(stderr);
+ }
#elif defined(Q_OS_ANDROID)
static bool logToAndroid = qEnvironmentVariableIsEmpty("QT_ANDROID_PLAIN_LOG");
if (logToAndroid) {