From 466e0dff4bb686e51d0ab3f905631fcb7dd8bfef Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 19 Sep 2013 17:15:43 +0200 Subject: [PATCH] Add tracing to logging framework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I4d5b9a24a214785019ff1238c1790ead79205b15 Reviewed-by: Leena Miettinen Reviewed-by: Topi Reiniƶ Reviewed-by: Robin Burchell Reviewed-by: Thiago Macieira Reviewed-by: Shawn Rutledge --- src/corelib/doc/snippets/qtracer/ftracer.cpp | 180 ++++++++++++ src/corelib/doc/snippets/qtracer/main.cpp | 59 ++++ src/corelib/doc/snippets/qtracer/qtracer.pro | 2 + src/corelib/global/qglobal.cpp | 4 + src/corelib/global/qlogging.cpp | 1 + src/corelib/global/qlogging.h | 2 +- src/corelib/io/qloggingcategory.cpp | 293 ++++++++++++++++++- src/corelib/io/qloggingcategory.h | 74 ++++- src/corelib/io/qloggingregistry.cpp | 8 + src/testlib/qtestlog.cpp | 1 + 10 files changed, 618 insertions(+), 6 deletions(-) create mode 100644 src/corelib/doc/snippets/qtracer/ftracer.cpp create mode 100644 src/corelib/doc/snippets/qtracer/main.cpp create mode 100644 src/corelib/doc/snippets/qtracer/qtracer.pro diff --git a/src/corelib/doc/snippets/qtracer/ftracer.cpp b/src/corelib/doc/snippets/qtracer/ftracer.cpp new file mode 100644 index 0000000000..b12e3ed9c3 --- /dev/null +++ b/src/corelib/doc/snippets/qtracer/ftracer.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include + + +//![1] +QLoggingCategory theFooArea("foo"); +QLoggingCategory theBarArea("bar"); +QLoggingCategory theBazArea("baz"); +//![1] + +// Note: These locations are Ubuntu specific. + +// Note: To make the example work with user permissions, make sure +// the files are user-writable and the path leading there accessible. + +const char traceSwitch[] = "/sys/kernel/debug/tracing/tracing_on"; +const char traceSink[] = "/sys/kernel/debug/tracing/trace_marker"; + +// The base class only serves as a facility to share code +// between the "single line" data logging aspect and the +// scoped "measuring" aspect. + +// Both aspects and the base class could be combined into +// a single tracer serving both purposes, but are split +// here for clarity. + +// Error handling is left as an exercise. + +//![2] +class MyTracerBase : public QTracer +{ +public: + MyTracerBase() { + enable = ::open(traceSwitch, O_WRONLY); + marker = ::open(traceSink, O_WRONLY); + } + + ~MyTracerBase() { + ::close(enable); + ::close(marker); + } + +protected: + int enable; + int marker; +}; +//![2] + + +//![2] +class MyTracer : public MyTracerBase +{ +public: + void start() { ::write(marker, "B", 1); } + void end() { ::write(marker, "E", 1); } +}; +//![2] + + +//![3] +class MyDataLogger : public MyTracerBase +{ +public: + MyDataLogger() { + buf[0] = 0; + pos = 0; + } + + void record(int i) { pos += sprintf(buf + pos, "%d", i); } + void record(const char *msg) { pos += sprintf(buf + pos, "%s", msg); } + void end() { ::write(marker, buf, pos); pos = 0; } + +private: + char buf[100]; + int pos; +}; +//![3] + +// Simplest possible example for "measuring". +//![4] +int foo(int i) +{ + qCTraceGuard(theFooArea); + // Here could be some lengthy code. + return i * i; +} +//![4] + +// We can switch on/off tracing dynamically. +// The tracer will be temporarily switched off at the third call +// and re-enabled at the eighth. +//![5] +int bar(int i) +{ + static int n = 0; + ++n; + if (n == 3) + theBarArea.setEnabled(QtTraceMsg, false); + if (n == 8) + theBarArea.setEnabled(QtTraceMsg, true); + + qCTraceGuard(theBarArea); + return i * i; +} +//![5] + +// An example to create "complex" log messages. +//![6] +int baz(int i) +{ + qCTrace(theBazArea) << 32 << "some stuff"; + + return i * i; +} +//![6] + + + +//![7] +namespace { +static struct Init +{ + Init() { + tracer.addToCategory(theFooArea); + tracer.addToCategory(theBarArea); + logger.addToCategory(theBazArea); + } + + MyTracer tracer; + MyDataLogger logger; + +} initializer; +} +//![7] diff --git a/src/corelib/doc/snippets/qtracer/main.cpp b/src/corelib/doc/snippets/qtracer/main.cpp new file mode 100644 index 0000000000..758a2bbdb8 --- /dev/null +++ b/src/corelib/doc/snippets/qtracer/main.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +int foo(int i); +int bar(int i); +int baz(int i); + +int main() +{ + int s = 0; + for (int i = 0; i != 10; ++i) + s += foo(i); + + for (int i = 0; i != 10; ++i) + s += bar(i); + + for (int i = 0; i != 10; ++i) + s += baz(i); + + return s; +} + diff --git a/src/corelib/doc/snippets/qtracer/qtracer.pro b/src/corelib/doc/snippets/qtracer/qtracer.pro new file mode 100644 index 0000000000..254e22be76 --- /dev/null +++ b/src/corelib/doc/snippets/qtracer/qtracer.pro @@ -0,0 +1,2 @@ + +SOURCES += ftracer.cpp main.cpp diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 59bdecc868..e2b1502a8e 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -717,6 +717,10 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n); A message generated by the qCritical() function. \value QtFatalMsg A message generated by the qFatal() function. + \value QtTraceMsg + Used by the qCTrace() macro. Trace events are usually passed only + to dedicated \a QTracer objects, and do not appear in the installed + message handler. \value QtSystemMsg diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 4d564b09c3..c0709ce258 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -814,6 +814,7 @@ Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogCont case QtWarningMsg: message.append(QLatin1String("warning")); break; case QtCriticalMsg:message.append(QLatin1String("critical")); break; case QtFatalMsg: message.append(QLatin1String("fatal")); break; + case QtTraceMsg: message.append(QLatin1String("trace")); break; } } else if (token == fileTokenC) { if (context.file) diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h index 2b798f9ea0..68a24d0397 100644 --- a/src/corelib/global/qlogging.h +++ b/src/corelib/global/qlogging.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE class QDebug; class QNoDebug; -enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtSystemMsg = QtCriticalMsg }; +enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtTraceMsg, QtSystemMsg = QtCriticalMsg }; class QMessageLogContext { diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index 562cf25964..80acee6ad1 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -107,7 +107,8 @@ QLoggingCategory::QLoggingCategory(const char *category) : name(0), enabledDebug(false), enabledWarning(true), - enabledCritical(true) + enabledCritical(true), + enabledTrace(false) { bool isDefaultCategory = (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0); @@ -122,7 +123,8 @@ QLoggingCategory::QLoggingCategory(const char *category) } if (QLoggingRegistry *reg = QLoggingRegistry::instance()) - reg->registerCategory(this);} + reg->registerCategory(this); +} /*! Destructs a QLoggingCategory object @@ -164,6 +166,7 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const case QtDebugMsg: return enabledDebug; case QtWarningMsg: return enabledWarning; case QtCriticalMsg: return enabledCritical; + case QtTraceMsg: return enabledTrace; case QtFatalMsg: return true; default: break; } @@ -177,6 +180,10 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const change e.g. the settings of another objects for the same category name. \note QtFatalMsg cannot be changed. It will always return true. + + Example: + + \snippet qtracer/ftracer.cpp 5 */ void QLoggingCategory::setEnabled(QtMsgType type, bool enable) { @@ -184,6 +191,7 @@ void QLoggingCategory::setEnabled(QtMsgType type, bool enable) case QtDebugMsg: enabledDebug = enable; break; case QtWarningMsg: enabledWarning = enable; break; case QtCriticalMsg: enabledCritical = enable; break; + case QtTraceMsg: enabledTrace = enable; break; case QtFatalMsg: default: break; } @@ -319,11 +327,60 @@ void QLoggingCategory::setFilterRules(const QString &rules) \snippet qloggingcategory/main.cpp 12 \note Arguments are not processed if critical output for the category is not - enabled, so do not reply on any side effects. + enabled, so do not rely on any side effects. \sa qCritical() */ +/*! + \relates QLoggingCategory + \macro qCTrace(category) + \since 5.2 + + Returns an output stream for trace messages in the logging category + \a category. + + The macro expands to code that first checks whether + \l QLoggingCategory::isEnabled() evaluates for trace output to \c{true}. + If so, the stream arguments are processed and sent to the tracers + registered with the category. + + \note Arguments are not processed if trace output for the category is not + enabled, so do not rely on any side effects. + + Example: + + \snippet qtracer/ftracer.cpp 6 + + \sa qCTraceGuard() +*/ + +/*! + \relates QLoggingCategory + \macro qCTraceGuard(category) + \since 5.2 + + The macro expands to code that creates a guard object with automatic + storage. The guard constructor checks whether + \l QLoggingCategory::isEnabled() evaluates for trace output to \c{true}. + If so, the stream arguments are processed and the \c{start()} + functions of the tracers registered with the \a category are called. + + The guard destructor also checks whether the category is enabled for + tracing and if so, the \c{end()} + functions of the tracers registered with the \a category are called. + + \note Arguments are always processed, even if trace output for the + category is disabled. They will, however, in that case not be passed + to the \c{record()} functions of the registered tracers. + + Example: + + \snippet qtracer/ftracer.cpp 4 + + \sa qCTrace() +*/ + /*! \macro Q_DECLARE_LOGGING_CATEGORY(name) \relates QLoggingCategory @@ -349,4 +406,234 @@ void QLoggingCategory::setFilterRules(const QString &rules) This macro must be used outside of a class or method. */ + +/*! + \class QTracer + \inmodule QtCore + \since 5.2 + + \brief The QTracer class provides an interface for handling + trace events associated with a logging category. + + \c QTracer objects are registered with logging categories. + Multiple \c QTracer objects + can be registered with the same category, and the same + \c QTracer object can be registered with different categories. + + If code containing \c qCTrace is executed, and the associated + logging category is enabled for tracing, all \c QTracer objects + that are registered with the category are notified. + + \c QTracer objects +*/ + +/*! + \fn QTracer::QTracer() + + Constructs a tracer object. + + Example: + + \snippet qtracer/ftracer.cpp 2 +*/ + +/*! + \fn QTracer::~QTracer() + + Destroys the tracer object. +*/ + +/*! + Registers this tracer for the \a category. + + The tracer will later be notified of messages of type + \c QtTraceMsg, as long as that message type + is enabled in the category. + + Example: + + \snippet qtracer/ftracer.cpp 1 + \codeline + \snippet qtracer/ftracer.cpp 7 +*/ + +void QTracer::addToCategory(QLoggingCategory &category) +{ + category.tracers.append(this); +} + +/*! + \fn void QTracer::start() + + This function is invoked when a tracing activity starts, + typically from the constructor of a \c QTraceGuard object + defined by \c qCTrace() or \c qCTraceGuard(). + + The base implementation does nothing. \c QTracer subclasses + are advised to override it if needed. + + \sa qCTrace(), qCTraceGuard() +*/ + +/*! + \fn void QTracer::end() + + This function is invoked when a tracing activity ends, + typically from the destructor of a \c QTraceGuard object + defined by \c qCTrace() or \c qCTraceGuard(). + + The base implementation does nothing. It is common for + \c QTracer subclasses to override it to perform flushing + of collected data. + + \sa qCTrace(), qCTraceGuard() +*/ + +/*! + \fn void QTracer::record(int data) + + This function is invoked during a tracing activity to + pass integer \a data to the \c QTracer object. + + Example: + + \snippet qtracer/ftracer.cpp 3 +*/ + +/*! + \fn void QTracer::record(const char *data) + + This function is invoked during a tracing activity to + pass string \a data to the \c QTracer object. +*/ + +/*! + \fn void QTracer::record(const QVariant &data) + + This function is invoked during a tracing activity to + pass abitrary (non-integer, non-string) \a data to + the \c QTracer object. +*/ + +/*! + \class QTraceGuard + \since 5.2 + \inmodule QtCore + + \brief The QTraceGuard class facilitates notifications to + \c QTracer objects. + + \c QTraceGuard objects are typically implicitly created on the + stack when using the \c qCTrace or \c qCTraceGuard macros and + are associated to a \c QLoggingCategory. + + The constructor of a \c QTraceGuard objects checks whether + its associated category is enabled, and if so, informs all + \c QTracer objects registered with the category that a + tracing activity starts. + + The destructor of a \c QTraceGuard objects checks whether + its associated category is enabled, and if so, informs all + \c QTracer objects registered with the category that a + tracing activity ended. + + A \c QTraceGuard object created by \c qCTrace will be destroyed + at the end of the full expression, a guard created by + \c qCTraceGuard at the end of the block containing the macro. + + During the lifetime of a QTraceGuard object, its \c operator<<() + can be used to pass additional data to the active tracers. + The fast path handles only \c int and \c{const char *} data, + but it is possible to use arbitrary values wrapped in \c QVariants. + + \sa QTracer +*/ + +/*! + \fn QTraceGuard::QTraceGuard(QLoggingCategory &category) + \internal + + Constructs a trace guard object relaying to \a category. +*/ + +/*! + \fn QTraceGuard::~QTraceGuard() + \internal + + Destroys the trace guard object. +*/ + +/*! + \internal + + Calls \c start() on all registered tracers. +*/ + +void QTraceGuard::start() +{ + QLoggingCategory::Tracers &tracers = target->tracers; + for (int i = tracers.size(); --i >= 0; ) + tracers.at(i)->start(); +} + +/*! + \internal + + Calls \c end() on all registered tracers. +*/ + +void QTraceGuard::end() +{ + QLoggingCategory::Tracers &tracers = target->tracers; + for (int i = tracers.size(); --i >= 0; ) + tracers.at(i)->end(); +} + + +/*! + \internal + + This function is called for int parameters passed to the + qCTrace stream. +*/ + +QTraceGuard &QTraceGuard::operator<<(int msg) +{ + QLoggingCategory::Tracers &tracers = target->tracers; + for (int i = tracers.size(); --i >= 0; ) + tracers.at(i)->record(msg); + return *this; +} + +/*! + \internal + + This function is called for string parameters passed to the + qCTrace stream. +*/ + +QTraceGuard &QTraceGuard::operator<<(const char *msg) +{ + QLoggingCategory::Tracers &tracers = target->tracers; + for (int i = tracers.size(); --i >= 0; ) + tracers.at(i)->record(msg); + return *this; +} + + +/*! + \internal + + This function is called for QVariant parameters passed to the + qCTrace stream. +*/ + +QTraceGuard &QTraceGuard::operator<<(const QVariant &msg) +{ + QLoggingCategory::Tracers &tracers = target->tracers; + for (int i = tracers.size(); --i >= 0; ) + tracers.at(i)->record(msg); + return *this; +} + QT_END_NAMESPACE diff --git a/src/corelib/io/qloggingcategory.h b/src/corelib/io/qloggingcategory.h index 90111c96fa..23b25b5e3f 100644 --- a/src/corelib/io/qloggingcategory.h +++ b/src/corelib/io/qloggingcategory.h @@ -44,9 +44,13 @@ #include #include +#include QT_BEGIN_NAMESPACE +class QTracer; +class QTraceGuard; + class Q_CORE_EXPORT QLoggingCategory { Q_DISABLE_COPY(QLoggingCategory) @@ -76,13 +80,18 @@ public: static void setFilterRules(const QString &rules); private: + friend class QLoggingRegistry; + friend class QTraceGuard; + friend class QTracer; + const char *name; bool enabledDebug; bool enabledWarning; bool enabledCritical; - - friend class QLoggingRegistry; + bool enabledTrace; + typedef QVector Tracers; + Tracers tracers; }; template <> @@ -103,6 +112,56 @@ inline bool QLoggingCategory::isEnabled() const return enabledCritical; } +template <> +inline bool QLoggingCategory::isEnabled() const +{ + return enabledTrace; +} + +class Q_CORE_EXPORT QTracer +{ + Q_DISABLE_COPY(QTracer) +public: + QTracer() {} + virtual ~QTracer() {} + + void addToCategory(QLoggingCategory &category); + + virtual void start() {} + virtual void end() {} + virtual void record(int) {} + virtual void record(const char *) {} + virtual void record(const QVariant &) {} +}; + +class Q_CORE_EXPORT QTraceGuard +{ + Q_DISABLE_COPY(QTraceGuard) +public: + QTraceGuard(QLoggingCategory &category) + { + target = category.isEnabled() ? &category : 0; + if (target) + start(); + } + + ~QTraceGuard() + { + if (target) + end(); + } + + QTraceGuard &operator<<(int msg); + QTraceGuard &operator<<(const char *msg); + QTraceGuard &operator<<(const QVariant &msg); + +private: + void start(); + void end(); + + QLoggingCategory *target; +}; + #define Q_DECLARE_LOGGING_CATEGORY(name) \ extern QLoggingCategory &name(); @@ -123,6 +182,17 @@ inline bool QLoggingCategory::isEnabled() const #define qCCritical(category) \ for (bool enabled = category().isEnabled(); enabled; enabled = false) \ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).critical() +#define qCTrace(category) \ + for (bool enabled = category.isEnabled(); enabled; enabled = false) \ + QTraceGuard(category) + + +#define Q_TRACE_GUARD_NAME_HELPER(line) qTraceGuard ## line +#define Q_TRACE_GUARD_NAME(line) Q_TRACE_GUARD_NAME_HELPER(line) + +#define qCTraceGuard(category) \ + QTraceGuard Q_TRACE_GUARD_NAME(__LINE__)(category); + #if defined(QT_NO_DEBUG_OUTPUT) # undef qCDebug diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index a82e6f65f4..885b51709d 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -86,6 +86,9 @@ int QLoggingRule::pass(const QString &categoryName, QtMsgType msgType) const case QtCriticalMsg: fullCategory += QLatin1String(".critical"); break; + case QtTraceMsg: + fullCategory += QLatin1String(".trace"); + break; default: break; } @@ -288,6 +291,7 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat) bool debug = (cat->categoryName() == qtDefaultCategoryName); bool warning = true; bool critical = true; + bool trace = true; QString categoryName = QLatin1String(cat->categoryName()); QLoggingRegistry *reg = QLoggingRegistry::instance(); @@ -301,11 +305,15 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat) filterpass = item.pass(categoryName, QtCriticalMsg); if (filterpass != 0) critical = (filterpass > 0); + filterpass = item.pass(categoryName, QtTraceMsg); + if (filterpass != 0) + trace = (filterpass > 0); } cat->setEnabled(QtDebugMsg, debug); cat->setEnabled(QtWarningMsg, warning); cat->setEnabled(QtCriticalMsg, critical); + cat->setEnabled(QtTraceMsg, trace); } diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index d094372d0b..10936f5c03 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -257,6 +257,7 @@ namespace QTest { } switch (type) { + case QtTraceMsg: case QtDebugMsg: QTest::TestLoggers::addMessage(QAbstractTestLogger::QDebug, msg); break;