diff options
Diffstat (limited to 'src/logger/qlogger.cpp')
-rw-r--r-- | src/logger/qlogger.cpp | 411 |
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 + + |