summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorKai Koehne <kai.koehne@digia.com>2014-02-04 16:35:26 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-11 20:59:15 +0100
commita2bfd114938e1fdd5067f2dac812a8d3a5d89fd3 (patch)
tree3a0341ab6973bc827c7e2c0f4787f23820d7adb3 /src/corelib/io
parentdc09a02e3a4ea93388197d7f8a0cfebe194e9886 (diff)
Allow configuration of logging rules from file system
Allow configuration of logging rules from outside of the application, either through a configuration file (.config/QtProject/qtlogging.ini), or through a file specified by a QT_LOGGING_CONF environment variable. The logging rules from the different sources are concatenated: First the rules from QtProject/qtlogging.ini are applied, then QLoggingCategory::setLoggingRules(), finally from the environment. This allows an application to overwrite/augment the system wide rules, and in turn that can be tailored for a specific run by setting a configuration in the environment variable. [ChangeLog][QtCore][Logging] The logging framework can now be configured with an .ini file. Change-Id: I442efde1b7e0a2ebe135c6f6e0a4b656483fe4b1 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qloggingcategory.cpp73
-rw-r--r--src/corelib/io/qloggingregistry.cpp129
-rw-r--r--src/corelib/io/qloggingregistry_p.h36
3 files changed, 181 insertions, 57 deletions
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index 5fa346dce5..168087659f 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -86,12 +86,62 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory,
In the default configuration \l isWarningEnabled() , \l isDebugEnabled() and
\l isCriticalEnabled() will return \c true.
- \section1 Changing the configuration of a category
+ \section1 Configuring Categories
- Use either \l setFilterRules() or \l installFilter() to
- configure categories, for example
+ Categories can be centrally configured by either setting logging rules,
+ or by installing a custom filter.
- \snippet qloggingcategory/main.cpp 2
+ \section2 Logging Rules
+
+ Logging rules allow to enable or disable logging for categories in a flexible
+ way. Rules are specified in text, where every line must have the format
+
+ \code
+ <category>[.<type>] = true|false
+ \endcode
+
+ \c <category> is the name of the category, potentially with \c{*} as a
+ wildcard symbol as the first or last character (or at both positions).
+ The optional \c <type> must be either \c debug, \c warning, or \c critical.
+ Lines that do not fit to his scheme are ignored.
+
+ Rules are evaluated in text order, from first to last. That is, if two rules
+ apply to a category/type, the rule that comes later is applied.
+
+ Rules can be set via \l setFilterRules(). Since Qt 5.3 logging rules
+ are also automatically loaded from the \c [rules] section of a logging
+ configuration file. Such configuration files are looked up in the QtProject
+ configuration directory, or explicitly set in a \c QT_LOGGING_CONF
+ environment variable.
+
+ Rules set by \l setFilterRules() take precedence over rules specified
+ in the QtProject configuration directory, and can, in turn, be
+ overwritten by rules from the configuration file specified by
+ \c QT_LOGGING_CONF.
+
+ Order of evaluation:
+ \list
+ \li Rules from QtProject/qlogging.ini
+ \li Rules set by \l setFilterRules()
+ \li Rules from file in \c QT_LOGGING_CONF
+ \endlist
+
+ The \c QtProject/qlogging.ini file is looked up in all directories returned
+ by QStandardPaths::GenericConfigLocation, e.g.
+
+ \list
+ \li on Mac OS X: \c ~/Library/Preferences
+ \li on Unix: \c ~/.config, \c /etc/xdg
+ \li on Windows: \c %LOCALAPPDATA%, \c %ProgramData%,
+ \l QCoreApplication::applicationDirPath(),
+ QCoreApplication::applicationDirPath() + \c "/data"
+ \endlist
+
+ \section2 Installing a Custom Filter
+
+ As a lower-level alternative to the text rules you can also implement a
+ custom filter via \l installFilter(). All filter rules are ignored in this
+ case.
\section1 Printing the category
@@ -278,27 +328,18 @@ QLoggingCategory::installFilter(QLoggingCategory::CategoryFilter filter)
Configures which categories and message types should be enabled through a
a set of \a rules.
- Each line in \a rules must have the format
-
- \code
- <category>[.<type>] = true|false
- \endcode
-
- where \c <category> is the name of the category, potentially with \c{*} as a
- wildcard symbol at the start and/or the end. The optional \c <type> must
- be either \c debug, \c warning, or \c critical.
-
Example:
\snippet qloggingcategory/main.cpp 2
\note The rules might be ignored if a custom category filter is installed
- with \l installFilter().
+ with \l installFilter(), or if the user defined a custom logging
+ configuration file in the \c QT_LOGGING_CONF environment variable.
*/
void QLoggingCategory::setFilterRules(const QString &rules)
{
- QLoggingRegistry::instance()->rulesParser.setRules(rules);
+ QLoggingRegistry::instance()->setApiRules(rules);
}
/*!
diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp
index fd25ff697e..b8fef16c0e 100644
--- a/src/corelib/io/qloggingregistry.cpp
+++ b/src/corelib/io/qloggingregistry.cpp
@@ -42,6 +42,10 @@
#include "qloggingregistry_p.h"
#include "qloggingcategory_p.h"
+#include <QtCore/qfile.h>
+#include <QtCore/qstandardpaths.h>
+#include <QtCore/qtextstream.h>
+
QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QLoggingRegistry, qtLoggingRegistry)
@@ -150,33 +154,38 @@ void QLoggingRule::parse()
}
/*!
+ \class QLoggingSettingsParser
+ \since 5.3
\internal
- Creates a new QLoggingRules object.
+
+ Parses a .ini file with the following format:
+
+ [rules]
+ rule1=[true|false]
+ rule2=[true|false]
+ ...
+
+ [rules] is the default section, and therefore optional.
*/
-QLoggingRulesParser::QLoggingRulesParser(QLoggingRegistry *registry) :
- registry(registry)
-{
-}
/*!
\internal
- Sets logging rules string.
+ Parses configuration from \a content.
*/
-void QLoggingRulesParser::setRules(const QString &content)
+void QLoggingSettingsParser::setContent(const QString &content)
{
QString content_ = content;
QTextStream stream(&content_, QIODevice::ReadOnly);
- parseRules(stream);
+ setContent(stream);
}
/*!
\internal
- Parses rules out of a QTextStream.
+ Parses configuration from \a stream.
*/
-void QLoggingRulesParser::parseRules(QTextStream &stream)
+void QLoggingSettingsParser::setContent(QTextStream &stream)
{
- QVector<QLoggingRule> rules;
-
+ _rules.clear();
while (!stream.atEnd()) {
QString line = stream.readLine();
@@ -184,31 +193,79 @@ void QLoggingRulesParser::parseRules(QTextStream &stream)
line = line.simplified();
line.remove(QLatin1Char(' '));
- const QStringList pair = line.split(QLatin1Char('='));
- if (pair.count() == 2) {
- const QString pattern = pair.at(0);
- bool enabled = (QString::compare(pair.at(1),
- QLatin1String("true"),
- Qt::CaseInsensitive) == 0);
- rules.append(QLoggingRule(pattern, enabled));
+ // comment
+ if (line.startsWith(QLatin1Char(';')))
+ continue;
+
+ if (line.startsWith(QLatin1Char('[')) && line.endsWith(QLatin1Char(']'))) {
+ // new section
+ _section = line.mid(1, line.size() - 2);
+ continue;
}
- }
- registry->setRules(rules);
+ if (_section == QLatin1String("rules")) {
+ int equalPos = line.indexOf(QLatin1Char('='));
+ if ((equalPos != -1)
+ && (line.lastIndexOf(QLatin1Char('=')) == equalPos)) {
+ const QString pattern = line.left(equalPos);
+ const QStringRef value = line.midRef(equalPos + 1);
+ bool enabled = (value.compare(QLatin1String("true"),
+ Qt::CaseInsensitive) == 0);
+ _rules.append(QLoggingRule(pattern, enabled));
+ }
+ }
+ }
}
/*!
\internal
- QLoggingPrivate constructor
+ QLoggingRegistry constructor
*/
QLoggingRegistry::QLoggingRegistry()
- : rulesParser(this),
- categoryFilter(defaultCategoryFilter)
+ : categoryFilter(defaultCategoryFilter)
{
}
/*!
\internal
+ Initializes the rules database by loading
+ .config/QtProject/qtlogging.ini and $QT_LOGGING_CONF.
+ */
+void QLoggingRegistry::init()
+{
+ // get rules from environment
+ const QByteArray rulesFilePath = qgetenv("QT_LOGGING_CONF");
+ if (!rulesFilePath.isEmpty()) {
+ QFile file(QFile::decodeName(rulesFilePath));
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QTextStream stream(&file);
+ QLoggingSettingsParser parser;
+ parser.setContent(stream);
+ envRules = parser.rules();
+ }
+ }
+
+ // get rules from qt configuration
+ QString envPath = QStandardPaths::locate(QStandardPaths::GenericConfigLocation,
+ QStringLiteral("QtProject/qtlogging.ini"));
+ if (!envPath.isEmpty()) {
+ QFile file(envPath);
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QTextStream stream(&file);
+ QLoggingSettingsParser parser;
+ parser.setContent(stream);
+ configRules = parser.rules();
+ }
+ }
+
+ if (!envRules.isEmpty() || !configRules.isEmpty()) {
+ QMutexLocker locker(&registryMutex);
+ updateRules();
+ }
+}
+
+/*!
+ \internal
Registers a category object.
This method might be called concurrently for the same category object.
@@ -236,17 +293,33 @@ void QLoggingRegistry::unregisterCategory(QLoggingCategory *cat)
/*!
\internal
- Activates a new set of logging rules for the default filter.
-*/
-void QLoggingRegistry::setRules(const QVector<QLoggingRule> &rules_)
+ Installs logging rules as specified in \a content.
+ */
+void QLoggingRegistry::setApiRules(const QString &content)
{
+ QLoggingSettingsParser parser;
+ parser.setSection(QStringLiteral("rules"));
+ parser.setContent(content);
+
QMutexLocker locker(&registryMutex);
+ apiRules = parser.rules();
- rules = rules_;
+ updateRules();
+}
+/*!
+ \internal
+ Activates a new set of logging rules for the default filter.
+
+ (The caller must lock registryMutex to make sure the API is thread safe.)
+*/
+void QLoggingRegistry::updateRules()
+{
if (categoryFilter != defaultCategoryFilter)
return;
+ rules = configRules + apiRules + envRules;
+
foreach (QLoggingCategory *cat, categories)
(*categoryFilter)(cat);
}
diff --git a/src/corelib/io/qloggingregistry_p.h b/src/corelib/io/qloggingregistry_p.h
index cbf7aecc4f..d4b97d42b8 100644
--- a/src/corelib/io/qloggingregistry_p.h
+++ b/src/corelib/io/qloggingregistry_p.h
@@ -60,6 +60,8 @@
#include <QtCore/qtextstream.h>
#include <QtCore/qvector.h>
+class tst_QLoggingRegistry;
+
QT_BEGIN_NAMESPACE
class QLoggingRule
@@ -89,45 +91,53 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QLoggingRule::PatternFlags)
Q_DECLARE_TYPEINFO(QLoggingRule, Q_MOVABLE_TYPE);
-class QLoggingRulesParser
+class Q_AUTOTEST_EXPORT QLoggingSettingsParser
{
-private:
- explicit QLoggingRulesParser(class QLoggingRegistry *logging);
-
public:
- void setRules(const QString &content);
+ void setSection(const QString &section) { _section = section; }
-private:
- void parseRules(QTextStream &stream);
- QLoggingRegistry *registry;
+ void setContent(const QString &content);
+ void setContent(QTextStream &stream);
+
+ QVector<QLoggingRule> rules() const { return _rules; }
- friend class QLoggingRegistry;
+private:
+ QString _section;
+ QVector<QLoggingRule> _rules;
};
-class QLoggingRegistry
+class Q_AUTOTEST_EXPORT QLoggingRegistry
{
public:
QLoggingRegistry();
+ void init();
+
void registerCategory(QLoggingCategory *category);
void unregisterCategory(QLoggingCategory *category);
- void setRules(const QVector<QLoggingRule> &rules);
+ void setApiRules(const QString &content);
QLoggingCategory::CategoryFilter
installFilter(QLoggingCategory::CategoryFilter filter);
static QLoggingRegistry *instance();
- QLoggingRulesParser rulesParser;
-
private:
+ void updateRules();
+
static void defaultCategoryFilter(QLoggingCategory *category);
QMutex registryMutex;
+
+ QVector<QLoggingRule> configRules;
+ QVector<QLoggingRule> envRules;
+ QVector<QLoggingRule> apiRules;
QVector<QLoggingRule> rules;
QList<QLoggingCategory*> categories;
QLoggingCategory::CategoryFilter categoryFilter;
+
+ friend class ::tst_QLoggingRegistry;
};
QT_END_NAMESPACE