aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGergely Risko <gergely+context@risko.hu>2009-08-31 17:18:56 +0300
committerGergely Risko <gergely+context@risko.hu>2009-08-31 17:18:56 +0300
commit46148371547a214458e6becd64400ddd26e29102 (patch)
tree4803d4fc36d6662f123e114370cfdb9e63526976
parentfbbb9e16aed3c593907b909211cc3fde4cdc1e68 (diff)
Added QSet support to the logging framework.
-rw-r--r--common/logging.cpp165
-rw-r--r--common/logging.h26
2 files changed, 100 insertions, 91 deletions
diff --git a/common/logging.cpp b/common/logging.cpp
index c0b49e19..5f615647 100644
--- a/common/logging.cpp
+++ b/common/logging.cpp
@@ -27,21 +27,21 @@
/*!
\page Logging
-
- \brief The library (and ContexKit in general) use a simple logging system designed
+
+ \brief The library (and ContexKit in general) use a simple logging system designed
to unify the output and make the debugging easier.
-
+
\section API
-
- Four types of log messages (presented here in the order of importance) are supported:
- \b Test, \b Debug, \b Warning and \b Critical.
-
- The first one, the \b Test message requires some attention. It's meant to be used
+
+ Four types of log messages (presented here in the order of importance) are supported:
+ \b Test, \b Debug, \b Warning and \b Critical.
+
+ The first one, the \b Test message requires some attention. It's meant to be used
from tests and unit-tests to log various stages of the test execution. It'll make
the test output more easily filterable.
-
+
The log messages can be used like this:
-
+
\code
contextTest() << "This is some message";
contextDebug() << "My value is:" << someVariable;
@@ -49,7 +49,7 @@
contextCritical() << 5 << "is bigger than" << 4;
\endcode
- Notice that the logging framework (very much like ie \b qDebug) automatically
+ Notice that the logging framework (very much like ie \b qDebug) automatically
ads whitespace. So:
\code
@@ -61,65 +61,65 @@
\code
My value is 5 and should be 5
\endcode
-
+
\section compilecontrol Compile-time verbosity control
-
- During the compile time certain defines can be used to turn-off debug messages.
+
+ During the compile time certain defines can be used to turn-off debug messages.
Those defines are:
-
+
\code
CONTEXT_LOG_HIDE_TEST
CONTEXT_LOG_HIDE_DEBUG
CONTEXT_LOG_HIDE_WARNING
CONTEXT_LOG_HIDE_CRITICAL
\endcode
-
+
A given define makes a respective macro message evaluate to an empty code. To be precise:
it makes the macro message evaluate to an inline do-nothing class that is optimized by the
compiler to do nothing.
-
+
When ie. \c CONTEXT_LOG_HIDE_DEBUG define is used to turn off \c contextDebug()
- messages, the actual string content of the debug messages is \b not included in the binary
+ messages, the actual string content of the debug messages is \b not included in the binary
and during runtime the machine does not spend time evaluating it.
-
+
Those compile-time control defines are integrated in the build/configure system.
-
+
\section runtimecontrol Run-time verbosity control
-
+
During run-time, the amount of debugging can be limited (filtered) but it can't be increased
- (expanded). In other words, if a package was compiled with warnings-only, it's not possible
- to make it show debug messages at runtime. But it is possible to make it criticals-only.
-
+ (expanded). In other words, if a package was compiled with warnings-only, it's not possible
+ to make it show debug messages at runtime. But it is possible to make it criticals-only.
+
The filtering happens via env variables. The major player is the \c CONTEXT_LOG_VERBOSITY variable
- which can be set to \c TEST, \c DEBUG, \c WARNING and \c CRITICAL. The \c CONTEXT_LOG_VERBOSITY
- specifies the minimal level of the messages shown. Ie. \c CONTEXT_LOG_VERBOSITY set to
- \c WARNING will show only warning and criticals.
-
- The format of the output can be tweaked with \c CONTEXT_LOG_HIDE_TIMESTAMPS and \c CONTEXT_LOG_USE_COLOR.
- The first one makes the messages shorter by skipping the timestamp info. The second one adds a
+ which can be set to \c TEST, \c DEBUG, \c WARNING and \c CRITICAL. The \c CONTEXT_LOG_VERBOSITY
+ specifies the minimal level of the messages shown. Ie. \c CONTEXT_LOG_VERBOSITY set to
+ \c WARNING will show only warning and criticals.
+
+ The format of the output can be tweaked with \c CONTEXT_LOG_HIDE_TIMESTAMPS and \c CONTEXT_LOG_USE_COLOR.
+ The first one makes the messages shorter by skipping the timestamp info. The second one adds a
little bit of ANSI coloring to the messages.
-
- \c CONTEXT_LOG_SHOW_MODULE will filter-out (kill) all messages \b except the ones coming from the
+
+ \c CONTEXT_LOG_SHOW_MODULE will filter-out (kill) all messages \b except the ones coming from the
specified module. Ie.:
-
+
\code
CONTEXT_LOG_SHOW_MODULE="subscriber" ./some-binary
\endcode
-
+
...will run \c ./some-binary showing log messages \b only from \c subscriber module.
-
- Lastly, \c CONTEXT_LOG_HIDE_MODULE will hide log messages coming from the specified module.
+
+ Lastly, \c CONTEXT_LOG_HIDE_MODULE will hide log messages coming from the specified module.
All other messages will be show.
\section modules Modules in logging
- In previous section we discussed and mentioned modules. For the purpose of logging,
+ In previous section we discussed and mentioned modules. For the purpose of logging,
a module is a piece of code (not neccesarily limited to one binary or shared object) that
forms one component (feature-wise). Specyfying and naming the modules is used
- to set the origin of the logging messages.
+ to set the origin of the logging messages.
The logging module is set using the \c CONTEXT_LOG_MODULE_NAME define. It should be
- (in most cases) defined in the build system and automatically applied to the whole source code.
+ (in most cases) defined in the build system and automatically applied to the whole source code.
Typically (with autotools) this can be achieved with something similar too:
\code
@@ -127,42 +127,42 @@
AM_CXXFLAGS = '-DCONTEXT_LOG_MODULE_NAME="libtest"'
...
\endcode
-
+
If \c CONTEXT_LOG_MODULE_NAME is undefined, the log messages will be marked as coming from an
\b "Undefined" module.
\section features Featues
- It's possible also to assign logging messages to feature groups and control the output
- based on that. Features can be compared to tags - one message can belong to zero or more
+ It's possible also to assign logging messages to feature groups and control the output
+ based on that. Features can be compared to tags - one message can belong to zero or more
features. To add to a feature to a log message:
- \code
+ \code
contextDebug() << contextFeature("threads") << "Message goes here" << someVariable;
contextDebug() << contextFeature("threads") << contextFeature("something") << "Message...";
\endcode
- It doesn't matter where features are added to the message. There is no specific order required.
+ It doesn't matter where features are added to the message. There is no specific order required.
The following syntax is supported as well:
\code
contextDebug() << contextFeature("threads") << "Some message..." << contextFeature("another");
\endcode
- There are two enviornment variables that control the output of messages vs. features: \b
+ There are two enviornment variables that control the output of messages vs. features: \b
CONTEXT_LOG_SHOW_FEATURES and \b CONTEXT_LOG_HIDE_FEATURES. Both take a comma-separated
- list of features.
+ list of features.
If you specify CONTEXT_LOG_SHOW_FEATURES only messages with given features will be printed to
the screen. If you specify \b CONTEXT_LOG_HIDE_FEATURES, messages with the specified features
- will be hidden (not displayed). For example:
+ will be hidden (not displayed). For example:
\code
CONTEXT_LOG_SHOW_FEATURES="threads,util" ./some-binary
\endcode
- ...will make \b only the messages belonging to "threads" or "util" features displayed.
+ ...will make \b only the messages belonging to "threads" or "util" features displayed.
\code
CONTEXT_LOG_HIDE_FEATURES="threads,util" ./some-binary
@@ -173,8 +173,8 @@
\section vanilla Vanilla
If the default logging output is too much for you, it's possible to set a CONTEXT_LOG_VANILLA
- enviornment variable. This will simplify the logging output greatly -- no timestamps will be printed,
- no module information will be printed, no line/function/class info will be printed.
+ enviornment variable. This will simplify the logging output greatly -- no timestamps will be printed,
+ no module information will be printed, no line/function/class info will be printed.
*/
/* ContextFeature */
@@ -187,14 +187,14 @@
A feature can be ie. "multithreading", "introspection", "dbus" or anything that makes sense
in your setup. Using features you can later get more filtered debug output. You most likely
want to use this class like this:
-
-
+
+
\code
...
contextDebug() << ContextFeature("introspection") << "Message";
...
\endcode
-
+
One message can belong to many features or to none.
*/
@@ -232,10 +232,10 @@ bool ContextRealLogger::vanilla = false;
QStringList ContextRealLogger::showFeatures = QStringList();
QStringList ContextRealLogger::hideFeatures = QStringList();
-/// Initialize the class by checking the enviornment variables and setting
+/// Initialize the class by checking the enviornment variables and setting
/// the message output params. The log level is set from \c CONTEXT_LOG_VERBOSITY
/// and from this env var the showTest, showDebug, showWarning... are set. By default
-/// everything is displayed at runtime. It's also possible to not show timestamps in
+/// everything is displayed at runtime. It's also possible to not show timestamps in
/// messages and spice-up the output with some color.
void ContextRealLogger::initialize()
{
@@ -244,18 +244,18 @@ void ContextRealLogger::initialize()
if (getenv("CONTEXT_LOG_USE_COLOR") != NULL)
useColor = true;
-
+
// Check feature enablers (showFeatures)
const char *showFeaturesStr = getenv("CONTEXT_LOG_SHOW_FEATURES");
if (showFeaturesStr) {
- foreach (QString f, QString(showFeaturesStr).split(','))
+ foreach (QString f, QString(showFeaturesStr).split(','))
showFeatures << f.trimmed();
}
-
+
// Check feature hide (hideFeatures)
const char *hideFeaturesStr = getenv("CONTEXT_LOG_HIDE_FEATURES");
if (hideFeaturesStr) {
- foreach (QString f, QString(hideFeaturesStr).split(','))
+ foreach (QString f, QString(hideFeaturesStr).split(','))
hideFeatures << f.trimmed();
}
@@ -264,14 +264,14 @@ void ContextRealLogger::initialize()
hideModule = getenv("CONTEXT_LOG_HIDE_MODULE");
// Vanilla
- if (getenv("CONTEXT_LOG_VANILLA"))
+ if (getenv("CONTEXT_LOG_VANILLA"))
vanilla = true;
// Check and do verbosity
const char *verbosity = getenv("CONTEXT_LOG_VERBOSITY");
if (! verbosity)
verbosity = "WARNING";
-
+
if (strcmp(verbosity, "TEST") == 0) {
// Do nothing, all left true
} else if (strcmp(verbosity, "DEBUG") == 0) {
@@ -289,23 +289,23 @@ void ContextRealLogger::initialize()
showDebug = false;
showWarning = false;
}
-
+
initialized = true;
}
/// Constructor. Called by the macros. \a func is the function name, \a file is
/// is the current source file and \a line specifies the line number.
-ContextRealLogger::ContextRealLogger(int type, const char *module, const char *func, const char *file, int line)
+ContextRealLogger::ContextRealLogger(int type, const char *module, const char *func, const char *file, int line)
: QTextStream(), msgType(type), moduleName(module)
{
if (! initialized) {
- // This is not thread safe, but our initialization depends on
+ // This is not thread safe, but our initialization depends on
// non-mutable parts anyways, so we should be ok.
initialize();
}
-
+
setString(&data);
-
+
// Add timestamp
if (! hideTimestamps && ! vanilla)
*this << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
@@ -313,7 +313,7 @@ ContextRealLogger::ContextRealLogger(int type, const char *module, const char *f
// Module name
if (! vanilla)
*this << QString("[" + QString(module) + "]");
-
+
// Message name
switch(type) {
case CONTEXT_LOG_MSG_TYPE_DEBUG:
@@ -335,7 +335,7 @@ ContextRealLogger::ContextRealLogger(int type, const char *module, const char *f
}
// File, line and function...
-
+
if (! vanilla)
*this << QString("[" + QString(file) + ":" + QString::number(line) + ":" + QString(func) + "]");
}
@@ -345,26 +345,26 @@ bool ContextRealLogger::shouldPrint()
// First try to eliminated based on message type...
if (msgType == CONTEXT_LOG_MSG_TYPE_DEBUG && ! showDebug)
return false;
- else if (msgType == CONTEXT_LOG_MSG_TYPE_WARNING && ! showWarning)
+ else if (msgType == CONTEXT_LOG_MSG_TYPE_WARNING && ! showWarning)
return false;
- else if (msgType == CONTEXT_LOG_MSG_TYPE_TEST && ! showTest)
+ else if (msgType == CONTEXT_LOG_MSG_TYPE_TEST && ! showTest)
return false;
- else if (msgType == CONTEXT_LOG_MSG_TYPE_CRITICAL && ! showCritical)
+ else if (msgType == CONTEXT_LOG_MSG_TYPE_CRITICAL && ! showCritical)
return false;
-
+
// Now try to eliminate based on module name...
- if (showModule && strcmp(showModule, moduleName) != 0)
+ if (showModule && strcmp(showModule, moduleName) != 0)
return false;
-
- if (hideModule && strcmp(hideModule, moduleName) == 0)
+
+ if (hideModule && strcmp(hideModule, moduleName) == 0)
return false;
-
+
// Now try to eliminate by feature name
foreach(QString feature, features) {
if (hideFeatures.contains(feature))
return false;
}
-
+
if (showFeatures.length() > 0) {
foreach(QString feature, showFeatures) {
if (features.contains(feature))
@@ -372,7 +372,7 @@ bool ContextRealLogger::shouldPrint()
}
return false;
}
-
+
return true;
}
@@ -381,16 +381,16 @@ void ContextRealLogger::appendFeatures()
{
if (features.length() == 0)
return;
-
+
QTextStream::operator<<('[');
int i;
-
+
for (i = 0; i < features.length(); i++) {
QTextStream::operator<<(QString("#" + features.at(i)));
if (i < features.length() - 1)
QTextStream::operator<<(", ");
}
-
+
QTextStream::operator<<(']');
}
@@ -409,7 +409,7 @@ ContextRealLogger::~ContextRealLogger()
QTextStream::operator<<('\n');
QTextStream(stderr) << data;
}
-
+
setDevice(NULL);
}
@@ -516,4 +516,3 @@ ContextRealLogger& ContextRealLogger::operator<< (char v)
QTextStream::operator<<(' ');
return *this;
}
-
diff --git a/common/logging.h b/common/logging.h
index dfd9a4e9..65a5cc16 100644
--- a/common/logging.h
+++ b/common/logging.h
@@ -27,6 +27,8 @@
#include <QStringList>
#include <QTextStream>
#include <QBuffer>
+#include <QSet>
+#include <QDebug>
#define CONTEXT_LOG_MSG_TYPE_TEST 1
#define CONTEXT_LOG_MSG_TYPE_DEBUG 2
@@ -42,7 +44,7 @@ class ContextFeature
public:
ContextFeature(QString name);
QString getName() const;
-
+
private:
QString featureName;
};
@@ -52,7 +54,7 @@ class ContextRealLogger : public QTextStream
public:
ContextRealLogger(int msgType, const char *module, const char *func, const char *file, int line);
~ContextRealLogger();
-
+
static bool showTest; ///< Test messages enabled at runtime
static bool showDebug; ///< Debug messages enabled at runtime
static bool showWarning; ///< Warning messages enabled at runtime
@@ -65,9 +67,9 @@ public:
static QStringList showFeatures; ///< Show messages with \b only the specified features
static QStringList hideFeatures; ///< Hide messages with the specified features
static bool vanilla; ///< Use vanilla (stripped-down) logging
-
+
static void initialize();
-
+
ContextRealLogger &operator<< (const ContextFeature&);
virtual ContextRealLogger &operator<< (QChar);
@@ -83,9 +85,16 @@ public:
virtual ContextRealLogger &operator<< (const QString&);
virtual ContextRealLogger &operator<< (const char *);
virtual ContextRealLogger &operator<< (char);
-
+ template <typename T> ContextRealLogger &operator<< (const QSet<T>& set)
+ {
+ QString out;
+ QDebug(&out) << set;
+ QTextStream::operator<<(out);
+ return *this;
+ }
+
private:
-
+
bool shouldPrint();
void appendFeatures();
@@ -100,7 +109,7 @@ private:
\brief A fake logging class.
- When a certain debug message is disabled at a compile-time the debug macros expand to
+ When a certain debug message is disabled at a compile-time the debug macros expand to
this class. It has all functions declared as \b inline and fundamentally kills all input
targeted at it. The compiler optimizes the \b inline by not calling the functions at all and
not storing the strings at all.
@@ -111,7 +120,7 @@ class ContextZeroLogger
public:
/// Constructor. Does nothing.
inline ContextZeroLogger() {}
-
+
/* Stubby ops */
inline ContextZeroLogger &operator<< (QChar) { return *this;} ///< Does nothing.
inline ContextZeroLogger &operator<< (char) { return *this;} ///< Does nothing.
@@ -127,6 +136,7 @@ public:
inline ContextZeroLogger &operator<< (const QString&) { return *this;} ///< Does nothing.
inline ContextZeroLogger &operator<< (void *) { return *this;} ///< Does nothing.
inline ContextZeroLogger &operator<< (const ContextFeature&) { return *this;} ///< Does nothing.
+ template <typename T> inline ContextZeroLogger &operator<< (const QSet<T>&) { return *this;} ///< Does nothing.
};
/* Macro defs */