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>
This commit is contained in:
parent
774d74df91
commit
466e0dff4b
180
src/corelib/doc/snippets/qtracer/ftracer.cpp
Normal file
180
src/corelib/doc/snippets/qtracer/ftracer.cpp
Normal file
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
|
||||
//![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]
|
59
src/corelib/doc/snippets/qtracer/main.cpp
Normal file
59
src/corelib/doc/snippets/qtracer/main.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
2
src/corelib/doc/snippets/qtracer/qtracer.pro
Normal file
2
src/corelib/doc/snippets/qtracer/qtracer.pro
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
SOURCES += ftracer.cpp main.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
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -257,6 +257,7 @@ namespace QTest {
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case QtTraceMsg:
|
||||
case QtDebugMsg:
|
||||
QTest::TestLoggers::addMessage(QAbstractTestLogger::QDebug, msg);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user