summaryrefslogtreecommitdiffstats
path: root/src/logger/qlogger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/logger/qlogger.cpp')
-rw-r--r--src/logger/qlogger.cpp411
1 files changed, 411 insertions, 0 deletions
diff --git a/src/logger/qlogger.cpp b/src/logger/qlogger.cpp
new file mode 100644
index 0000000..302a6f4
--- /dev/null
+++ b/src/logger/qlogger.cpp
@@ -0,0 +1,411 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the logger module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QList>
+#include <QByteArray>
+#include <QString>
+#include <QFile>
+#include <QFileInfo>
+#include <QStandardPaths>
+#include <QBuffer>
+#include <QFileSystemWatcher>
+#include "qlogger_p.h"
+
+QT_USE_NAMESPACE
+QT_LOGGER_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QLoggingPrivate, qLogging)
+
+namespace QLoggingCategories
+{
+ bool _enabled = false;
+ QLoggingCategory default_QLoggingCategory("default");
+
+ QLoggingCategory::QLoggingCategory(const char *cat)
+ : _enabledDebug(false)
+ , _enabledWarning(true)
+ , _enabledCritical(true)
+ , _registered(false)
+ , _category(cat)
+ {}
+
+ bool QLoggingCategory::statusMessageType(const QtMsgType &type)
+ {
+ switch (type) {
+ case QtDebugMsg: return _enabledDebug;
+ case QtWarningMsg: return _enabledWarning;
+ case QtCriticalMsg: return _enabledCritical;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ void QLoggingCategory::setStatusMessageType(const QtMsgType &type, bool status)
+ {
+ switch (type) {
+ case QtDebugMsg: _enabledDebug = status;
+ case QtWarningMsg: _enabledWarning = status;
+ case QtCriticalMsg: _enabledCritical = status;
+ default:
+ break;
+ }
+ }
+
+ bool isEnabled(QLoggingCategories::QLoggingCategory &category, QtMsgType type)
+ {
+ return qLogging()->isEnabled(category, type);
+ }
+
+ bool isEnabled()
+ {
+ return _enabled;
+ }
+
+ QLoggingCategory& defaultCategory()
+ {
+ return default_QLoggingCategory;
+ }
+}
+
+void qSetLoggingRulesFile(const QString &path)
+{
+ qLogging()->setLoggingRulesFile(path);
+}
+
+void qSetLoggingRules(const QByteArray &rules)
+{
+ qLogging()->setLoggingRules(rules);
+}
+
+/*!
+ \internal
+ QLoggingPrivate constructor
+ */
+QLoggingPrivate::QLoggingPrivate()
+ : _configFileWatcher(0)
+{
+ //add default category
+ _registeredCategories.append(&QLoggingCategories::default_QLoggingCategory);
+
+ //Set the config file by using the envidonment variable QT_LOGGING_CONFIG
+ QByteArray ba = qgetenv("QT_LOGGING_CONFIG");
+ if (!ba.isEmpty()) {
+ setLoggingRulesFile(QString::fromLocal8Bit(ba));
+ _configFileEnvironmentVar = _configFile;
+ }
+}
+
+/*!
+ \internal
+ QLoggingPrivate destructor
+ */
+QLoggingPrivate::~QLoggingPrivate()
+{
+}
+
+/*!
+ \internal
+ Function to set the logging config file.
+ This function set the new QLogging configuration config file.
+ If QT_LOGGING_CONFIG is set this function will do nothing.
+*/
+void QLoggingPrivate::setLoggingRulesFile(const QString &path)
+{
+ if (!_configFileEnvironmentVar.isEmpty())
+ return;
+
+ //Default no logging
+ QLoggingCategories::_enabled = false;
+
+ //check the file if its only a filename
+ QFileInfo fi(path);
+ // If we have only a file, it lives in the config location
+ if (fi.fileName() == path)
+ fi.setFile(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + QLatin1Char('/') + path);
+ _configFile = fi.absoluteFilePath();
+
+ //Check if logging rule file exits
+ if (QFile::exists(_configFile)) {
+
+ //Create filewatcher only if a config file exists
+ if (!_configFileWatcher) {
+ _configFileWatcher = new QFileSystemWatcher(this);
+ connect(_configFileWatcher, SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString)));
+ }
+
+ QStringList oldfiles = _configFileWatcher->files();
+ if (!oldfiles.isEmpty())
+ _configFileWatcher->removePaths(oldfiles);
+ _configFileWatcher->addPath(_configFile);
+
+ QFile cfgfile(_configFile);
+ readSettings(cfgfile);
+ }
+}
+
+/*!
+ \internal
+ Function to set the logging rules.
+ This function set the new logging configuration.
+ If QT_LOGGING_CONFIG environment vaiable is in use, this function will not make any changes.
+*/
+void QLoggingPrivate::setLoggingRules(const QByteArray &rules)
+{
+ if (!_configFileEnvironmentVar.isEmpty())
+ return;
+
+ //Disable file watcher
+ if (_configFileWatcher) {
+ delete _configFileWatcher;
+ _configFileWatcher = 0;
+ }
+
+ //Default no logging
+ QLoggingCategories::_enabled = false;
+ QBuffer buffer;
+ buffer.setData(rules);
+ readSettings(buffer);
+}
+
+/*!
+ \internal
+ Slot for filewatcher
+*/
+void QLoggingPrivate::fileChanged(const QString &path)
+{
+ //check if the logging rule file was changed
+ if (path == _configFile){
+ QFile cfgfile(_configFile);
+ readSettings(cfgfile);
+ _configFileWatcher->addPath(path);
+ }
+}
+
+/*!
+ \internal
+ Reads the configuration out from a io device.
+*/
+void QLoggingPrivate::readSettings(QIODevice &device)
+{
+ QMutexLocker locker(&_mutex);
+ {
+ _logConfigItemList.clear();
+
+ if (device.open(QIODevice::ReadOnly)) {
+ QByteArray truearray("true");
+ QByteArray line;
+ while (!device.atEnd()) {
+ //Simplify the string before creating pair
+ line = device.readLine().replace(" ", "");
+ line = line.simplified();
+ const QList<QByteArray> pair = line.split('=');
+ if (pair.count() == 2)
+ _logConfigItemList.append(QLogConfigFilterItem(QString::fromLatin1(pair.at(0))
+ , (pair.at(1).toLower() == truearray)));
+ }
+ }
+
+ //Now all the categories are read, so we can update all known QLoggingCategories members.
+ foreach (QLoggingCategories::QLoggingCategory *category, _registeredCategories) {
+ updateCategory(category);
+ }
+
+ QLoggingCategories::_enabled = true;
+ }
+}
+
+/*!
+ \internal
+ Updates all the registered category members against the filter.
+*/
+void QLoggingPrivate::updateCategory(QLoggingCategories::QLoggingCategory *log)
+{
+ //set the default back (debug disable, warning and critical enabled)
+ if (log == &QLoggingCategories::default_QLoggingCategory) {
+ log->_enabledDebug = true;
+ log->_enabledWarning = true;
+ log->_enabledCritical = true;
+
+ } else {
+ log->_enabledDebug = false;
+ log->_enabledWarning = true;
+ log->_enabledCritical = true;
+ }
+
+ foreach (QLogConfigFilterItem item, _logConfigItemList) {
+ //Debug
+ int filterpass = item.pass(log, QtDebugMsg);
+ //apply filter if filterpass is not 0
+ if (filterpass != 0)
+ log->_enabledDebug = (filterpass > 0);
+ //Warning
+ filterpass = item.pass(log, QtWarningMsg);
+ if (filterpass != 0)
+ log->_enabledWarning = (filterpass > 0);
+ //Critical
+ filterpass = item.pass(log, QtCriticalMsg);
+ if (filterpass != 0)
+ log->_enabledCritical = (filterpass > 0);
+ }
+}
+
+/*!
+ \internal
+ Function that checks if the category is enabled and registered the category member if not already registered.
+*/
+bool QLoggingPrivate::isEnabled(QLoggingCategories::QLoggingCategory &category, QtMsgType type)
+{
+ if (category._registered)
+ return category.statusMessageType(type);
+
+ //category is unregistered.
+ //First update category (let it through the filter)
+ {
+ QMutexLocker locker(&_mutex);
+ //lock against _logConfigItemList between updateCategory and readSettings
+ updateCategory(&category);
+ category._registered = true;
+ _registeredCategories.append(&category);
+ }
+
+ return category.statusMessageType(type);
+}
+
+#define INVALID 0x00
+#define CATEGORY 0x01
+#define LEFTFILTER 0x02
+#define RIGHTFILTER 0x04
+#define MIDFILTER 0x06
+/*!
+ \internal
+ Constructor of a filter item.
+*/
+QLogConfigFilterItem::QLogConfigFilterItem(const QString &category, bool active)
+ : _category(category)
+ , _active(active)
+{
+ parse();
+}
+
+/*!
+ \internal
+ Parses the category and check witch kind of wildcard the filter can contain.
+ Allowed is f.e.g.:
+ com.Nokia.* LEFTFILTER
+ *.Nokia RIGHTFILTER
+ *.Nokia* MIDFILTER
+ */
+void QLogConfigFilterItem::parse()
+{
+ _type = INVALID;
+ int index = _category.indexOf(QString::fromLatin1("*"));
+ if (index < 0)
+ _type |= CATEGORY;
+ else {
+ if (index == 0) {
+ _type |= RIGHTFILTER;
+ _category = _category.remove(0, 1);
+ index = _category.indexOf(QString::fromLatin1("*"));
+ }
+ if (index == (_category.length() - 1)) {
+ _type |= LEFTFILTER;
+ _category = _category.remove(_category.length() - 1, 1);
+ }
+ }
+}
+
+/*!
+ \internal
+ return value 1 means filter passed, 0 means filter doesn't influence this category, -1 means category doesn't pass this filter
+ */
+int QLogConfigFilterItem::pass(const QLoggingCategories::QLoggingCategory *log, const QtMsgType &type)
+{
+ QString fullCategory = QString::fromLatin1(log->_category);
+ switch (type) {
+ case QtDebugMsg:
+ fullCategory += QString::fromLatin1(".debug");
+ break;
+ case QtWarningMsg:
+ fullCategory += QString::fromLatin1(".warning");
+ break;
+ case QtCriticalMsg:
+ fullCategory += QString::fromLatin1(".critical");
+ break;
+ default:
+ break;
+ }
+
+ if (_type == CATEGORY) {
+ //Can be
+ //NOKIA.com.debug = true
+ //or
+ //NOKIA.com = true
+ if (_category == QString::fromLatin1(log->_category) || _category == fullCategory)
+ return (_active ? 1 : -1);
+ }
+
+ int idx = 0;
+ if (_type == MIDFILTER) {
+ //e.g. *.Nokia*
+ idx = fullCategory.indexOf(_category);
+ if (idx >= 0)
+ return (_active ? 1 : -1);
+ } else {
+ idx = fullCategory.indexOf(_category);
+ if (_type == LEFTFILTER) {
+ //e.g. com.Nokia.*
+ if (idx == 0)
+ return (_active ? 1 : -1);
+ } else if (_type == RIGHTFILTER) {
+ //e.g. *.Nokia
+ if (idx == (fullCategory.count() - _category.count()))
+ return (_active ? 1 : -1);
+ }
+ }
+ return 0;
+}
+
+#include "moc_qlogger_p.cpp"
+
+QT_LOGGER_END_NAMESPACE
+
+