diff options
author | hjk <hjk121@nokiamail.com> | 2013-09-19 17:15:43 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-25 18:21:45 +0200 |
commit | 466e0dff4bb686e51d0ab3f905631fcb7dd8bfef (patch) | |
tree | 79ff471a646a15e38db12cb6b460dd48ea39cfbc /src/corelib/io | |
parent | 774d74df91869d1178cbcdc7648994576a47f850 (diff) |
Add tracing to logging framework
Change-Id: I4d5b9a24a214785019ff1238c1790ead79205b15
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@digia.com>
Reviewed-by: Topi Reiniƶ <topi.reinio@digia.com>
Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qloggingcategory.cpp | 293 | ||||
-rw-r--r-- | src/corelib/io/qloggingcategory.h | 74 | ||||
-rw-r--r-- | src/corelib/io/qloggingregistry.cpp | 8 |
3 files changed, 370 insertions, 5 deletions
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,12 +327,61 @@ 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 \since 5.2 @@ -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 <QtCore/qglobal.h> #include <QtCore/qdebug.h> +#include <QtCore/qvector.h> 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<QTracer *> Tracers; + Tracers tracers; }; template <> @@ -103,6 +112,56 @@ inline bool QLoggingCategory::isEnabled<QtCriticalMsg>() const return enabledCritical; } +template <> +inline bool QLoggingCategory::isEnabled<QtTraceMsg>() 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<QtTraceMsg>() ? &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<QtCriticalMsg>() const #define qCCritical(category) \ for (bool enabled = category().isEnabled<QtCriticalMsg>(); enabled; enabled = false) \ QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO, category().categoryName()).critical() +#define qCTrace(category) \ + for (bool enabled = category.isEnabled<QtTraceMsg>(); 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); } |