aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/corelib/logging
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@digia.com>2014-01-09 17:50:40 +0100
committerJoerg Bornemann <joerg.bornemann@digia.com>2014-01-10 18:11:22 +0100
commit81af9acaa295a574c1cb5e6714725197dac7f530 (patch)
treecc8c94467f49a7d267e5249f624874feecc7eed4 /src/lib/corelib/logging
parent2fe25eb3f20ffb4e58cb559f2bcb9950c963290a (diff)
Move Qt profile setup into a dedicated library.
Otherwise all changes to the implementation will have to be duplicated in IDEs. Change-Id: I61e6d4fa1ee9b724eb5d9de9f233dc915a6c8bc3 Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'src/lib/corelib/logging')
-rw-r--r--src/lib/corelib/logging/ilogsink.cpp118
-rw-r--r--src/lib/corelib/logging/ilogsink.h81
-rw-r--r--src/lib/corelib/logging/logger.cpp271
-rw-r--r--src/lib/corelib/logging/logger.h137
-rw-r--r--src/lib/corelib/logging/logging.pri14
-rw-r--r--src/lib/corelib/logging/translator.h47
6 files changed, 668 insertions, 0 deletions
diff --git a/src/lib/corelib/logging/ilogsink.cpp b/src/lib/corelib/logging/ilogsink.cpp
new file mode 100644
index 000000000..118fdf106
--- /dev/null
+++ b/src/lib/corelib/logging/ilogsink.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#include "ilogsink.h"
+
+#include <tools/error.h>
+
+#include <QByteArray>
+#include <QMutex>
+
+namespace qbs {
+
+QString logLevelTag(LoggerLevel level)
+{
+ if (level == LoggerInfo)
+ return QByteArray();
+ QString str = logLevelName(level).toUpper();
+ if (!str.isEmpty())
+ str.append(QLatin1String(": "));
+ return str;
+}
+
+QString logLevelName(LoggerLevel level)
+{
+ switch (level) {
+ case qbs::LoggerError:
+ return QLatin1String("error");
+ case qbs::LoggerWarning:
+ return QLatin1String("warning");
+ case qbs::LoggerInfo:
+ return QLatin1String("info");
+ case qbs::LoggerDebug:
+ return QLatin1String("debug");
+ case qbs::LoggerTrace:
+ return QLatin1String("trace");
+ default:
+ break;
+ }
+ return QString();
+}
+
+class ILogSink::ILogSinkPrivate
+{
+public:
+ LoggerLevel logLevel;
+ QMutex mutex;
+};
+
+ILogSink::ILogSink() : d(new ILogSinkPrivate)
+{
+ d->logLevel = defaultLogLevel();
+}
+
+ILogSink::~ILogSink()
+{
+ delete d;
+}
+
+void ILogSink::setLogLevel(LoggerLevel level)
+{
+ d->logLevel = level;
+}
+
+LoggerLevel ILogSink::logLevel() const
+{
+ return d->logLevel;
+}
+
+void ILogSink::printWarning(const ErrorInfo &warning)
+{
+ if (willPrint(LoggerWarning)) {
+ d->mutex.lock();
+ doPrintWarning(warning);
+ d->mutex.unlock();
+ }
+}
+
+void ILogSink::printMessage(LoggerLevel level, const QString &message, const QString &tag,
+ bool force)
+{
+ if (force || willPrint(level)) {
+ d->mutex.lock();
+ doPrintMessage(level, message, tag);
+ d->mutex.unlock();
+ }
+}
+
+void ILogSink::doPrintWarning(const ErrorInfo &warning)
+{
+ doPrintMessage(LoggerWarning, warning.toString(), QString());
+}
+
+} // namespace qbs
diff --git a/src/lib/corelib/logging/ilogsink.h b/src/lib/corelib/logging/ilogsink.h
new file mode 100644
index 000000000..9c263b52d
--- /dev/null
+++ b/src/lib/corelib/logging/ilogsink.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#ifndef QBS_ILOGSINK_H
+#define QBS_ILOGSINK_H
+
+#include "../tools/qbs_export.h"
+
+#include <QString>
+
+namespace qbs {
+class ErrorInfo;
+
+enum LoggerLevel
+{
+ LoggerMinLevel,
+ LoggerError = LoggerMinLevel,
+ LoggerWarning,
+ LoggerInfo,
+ LoggerDebug,
+ LoggerTrace,
+ LoggerMaxLevel = LoggerTrace
+};
+
+inline LoggerLevel defaultLogLevel() { return LoggerInfo; }
+QBS_EXPORT QString logLevelTag(LoggerLevel level);
+QBS_EXPORT QString logLevelName(LoggerLevel level);
+
+class QBS_EXPORT ILogSink
+{
+ Q_DISABLE_COPY(ILogSink)
+public:
+ ILogSink();
+ virtual ~ILogSink();
+
+ void setLogLevel(LoggerLevel level);
+ LoggerLevel logLevel() const;
+
+ bool willPrint(LoggerLevel level) const { return level <= logLevel(); }
+
+ void printWarning(const ErrorInfo &warning);
+ void printMessage(LoggerLevel level, const QString &message,
+ const QString &tag = QString(), bool force = false);
+
+private:
+ virtual void doPrintWarning(const ErrorInfo &warning);
+ virtual void doPrintMessage(LoggerLevel level, const QString &message,
+ const QString &tag) = 0;
+
+ class ILogSinkPrivate;
+ ILogSinkPrivate * const d;
+};
+
+} // namespace qbs
+
+#endif // Include guard
diff --git a/src/lib/corelib/logging/logger.cpp b/src/lib/corelib/logging/logger.cpp
new file mode 100644
index 000000000..9f7a19c01
--- /dev/null
+++ b/src/lib/corelib/logging/logger.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#if defined(_MSC_VER) && _MSC_VER > 0
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "logger.h"
+
+#include <QByteArray>
+#include <QElapsedTimer>
+#include <QMutex>
+#include <QSet>
+#include <QVariant>
+
+#include <cstdarg>
+#include <stdio.h>
+
+namespace qbs {
+namespace Internal {
+
+LogWriter::LogWriter(ILogSink *logSink, LoggerLevel level, bool force)
+ : m_logSink(logSink), m_level(level), m_force(force)
+{}
+
+LogWriter::LogWriter(const LogWriter &other)
+ : m_logSink(other.m_logSink)
+ , m_level(other.m_level)
+ , m_message(other.m_message)
+ , m_tag(other.m_tag)
+ , m_force(other.m_force)
+{
+ other.m_message.clear();
+}
+
+LogWriter::~LogWriter()
+{
+ if (!m_message.isEmpty())
+ m_logSink->printMessage(m_level, m_message, m_tag, m_force);
+}
+
+const LogWriter &LogWriter::operator=(const LogWriter &other)
+{
+ m_logSink = other.m_logSink;
+ m_level = other.m_level;
+ m_message = other.m_message;
+ m_tag = other.m_tag;
+ m_force = other.m_force;
+ other.m_message.clear();
+ return *this;
+}
+
+void LogWriter::write(char c)
+{
+ write(QLatin1Char(c));
+}
+
+void LogWriter::write(const char *str)
+{
+ write(QLatin1String(str));
+}
+
+void LogWriter::write(const QChar &c)
+{
+ if (m_force || m_logSink->logLevel() >= m_level)
+ m_message.append(c);
+}
+
+void LogWriter::write(const QString &message)
+{
+ if (m_force || m_logSink->logLevel() >= m_level)
+ m_message += message;
+}
+
+void LogWriter::setMessageTag(const QString &tag)
+{
+ m_tag = tag;
+}
+
+LogWriter operator<<(LogWriter w, const char *str)
+{
+ w.write(str);
+ return w;
+}
+
+LogWriter operator<<(LogWriter w, const QByteArray &byteArray)
+{
+ w.write(byteArray.data());
+ return w;
+}
+
+LogWriter operator<<(LogWriter w, const QString &str)
+{
+ w.write(str);
+ return w;
+}
+
+LogWriter operator<<(LogWriter w, const QStringList &strList)
+{
+ w.write('[');
+ for (int i = 0; i < strList.size(); ++i) {
+ w.write(strList.at(i));
+ if (i != strList.size() - 1)
+ w.write(QLatin1String(", "));
+ }
+ w.write(']');
+ return w;
+}
+
+LogWriter operator<<(LogWriter w, const QSet<QString> &strSet)
+{
+ bool firstLoop = true;
+ w.write('(');
+ foreach (const QString &str, strSet) {
+ if (firstLoop)
+ firstLoop = false;
+ else
+ w.write(QLatin1String(", "));
+ w.write(str);
+ }
+ w.write(')');
+ return w;
+}
+
+LogWriter operator<<(LogWriter w, const QVariant &variant)
+{
+ QString str = variant.typeName() + QLatin1Char('(');
+ if (variant.type() == QVariant::List) {
+ bool firstLoop = true;
+ foreach (const QVariant &item, variant.toList()) {
+ str += item.toString();
+ if (firstLoop)
+ firstLoop = false;
+ else
+ str += QLatin1String(", ");
+ }
+ } else {
+ str += variant.toString();
+ }
+ str += QLatin1Char(')');
+ w.write(str);
+ return w;
+}
+
+LogWriter operator<<(LogWriter w, int n)
+{
+ return w << QString::number(n);
+}
+
+LogWriter operator<<(LogWriter w, qint64 n)
+{
+ return w << QString::number(n);
+}
+
+LogWriter operator<<(LogWriter w, bool b)
+{
+ return w << QString(QLatin1String(b ? "true" : "false"));
+}
+
+LogWriter operator<<(LogWriter w, const MessageTag &tag)
+{
+ w.setMessageTag(tag.tag());
+ return w;
+}
+
+Logger::Logger(ILogSink *logger) : m_logSink(logger)
+{
+}
+
+bool Logger::debugEnabled() const
+{
+ return m_logSink->willPrint(LoggerDebug);
+}
+
+bool Logger::traceEnabled() const
+{
+ return m_logSink->willPrint(LoggerTrace);
+}
+
+LogWriter Logger::qbsLog(LoggerLevel level, bool force) const
+{
+ return LogWriter(m_logSink, level, force);
+}
+
+
+class TimedActivityLogger::TimedActivityLoggerPrivate
+{
+public:
+ Logger logger;
+ QString prefix;
+ QString activity;
+ LoggerLevel logLevel;
+ QElapsedTimer timer;
+ bool alwaysLog;
+};
+
+TimedActivityLogger::TimedActivityLogger(const Logger &logger, const QString &activity,
+ const QString &prefix, LoggerLevel logLevel, bool alwaysLog)
+ : d(0)
+{
+ if (!alwaysLog && !logger.logSink()->willPrint(logLevel))
+ return;
+ d = new TimedActivityLoggerPrivate;
+ d->logger = logger;
+ d->prefix = prefix;
+ d->activity = activity;
+ d->logLevel = logLevel;
+ d->alwaysLog = alwaysLog;
+ d->logger.qbsLog(logLevel, alwaysLog) << QString::fromLocal8Bit("%1Starting activity '%2'.")
+ .arg(prefix, activity);
+ d->timer.start();
+}
+
+void TimedActivityLogger::finishActivity()
+{
+ if (!d)
+ return;
+ qint64 ms = d->timer.elapsed();
+ qint64 s = ms/1000;
+ ms -= s*1000;
+ qint64 m = s/60;
+ s -= m*60;
+ const qint64 h = m/60;
+ m -= h*60;
+ QString timeString = QString::fromLocal8Bit("%1ms").arg(ms);
+ if (h || m || s)
+ timeString.prepend(QString::fromLocal8Bit("%1s, ").arg(s));
+ if (h || m)
+ timeString.prepend(QString::fromLocal8Bit("%1m, ").arg(m));
+ if (h)
+ timeString.prepend(QString::fromLocal8Bit("%1h, ").arg(h));
+ d->logger.qbsLog(d->logLevel, d->alwaysLog)
+ << QString::fromLocal8Bit("%1Activity '%2' took %3.")
+ .arg(d->prefix, d->activity, timeString);
+ delete d;
+ d = 0;
+}
+
+TimedActivityLogger::~TimedActivityLogger()
+{
+ finishActivity();
+}
+
+} // namespace Internal
+} // namespace qbs
diff --git a/src/lib/corelib/logging/logger.h b/src/lib/corelib/logging/logger.h
new file mode 100644
index 000000000..1ab11144d
--- /dev/null
+++ b/src/lib/corelib/logging/logger.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QBS_LOGGER_H
+#define QBS_LOGGER_H
+
+#include "ilogsink.h"
+
+#include <QByteArray>
+#include <QString>
+#include <QStringList>
+
+QT_BEGIN_NAMESPACE
+class QVariant;
+QT_END_NAMESPACE
+
+namespace qbs {
+namespace Internal {
+
+// Note that while these classes are not part of the API, we export some stuff for use by
+// our command line tools for the sake of a uniform logging approach.
+
+class QBS_EXPORT LogWriter
+{
+public:
+ LogWriter(ILogSink *logSink, LoggerLevel level, bool force = false);
+
+ // log writer has move semantics and the last instance of
+ // a << chain prints the accumulated data
+ LogWriter(const LogWriter &other);
+ ~LogWriter();
+ const LogWriter &operator=(const LogWriter &other);
+
+ void write(char c);
+ void write(const char *str);
+ void write(const QChar &c);
+ void write(const QString &message);
+
+ void setMessageTag(const QString &tag);
+
+private:
+ ILogSink *m_logSink;
+ LoggerLevel m_level;
+ mutable QString m_message;
+ QString m_tag;
+ bool m_force;
+};
+
+class QBS_EXPORT MessageTag
+{
+public:
+ explicit MessageTag(const QString &tag) : m_tag(tag) {}
+
+ const QString &tag() const { return m_tag; }
+
+private:
+ QString m_tag;
+};
+
+QBS_EXPORT LogWriter operator<<(LogWriter w, const char *str);
+QBS_EXPORT LogWriter operator<<(LogWriter w, const QByteArray &byteArray);
+QBS_EXPORT LogWriter operator<<(LogWriter w, const QString &str);
+QBS_EXPORT LogWriter operator<<(LogWriter w, const QStringList &strList);
+QBS_EXPORT LogWriter operator<<(LogWriter w, const QSet<QString> &strSet);
+QBS_EXPORT LogWriter operator<<(LogWriter w, const QVariant &variant);
+QBS_EXPORT LogWriter operator<<(LogWriter w, int n);
+QBS_EXPORT LogWriter operator<<(LogWriter w, qint64 n);
+QBS_EXPORT LogWriter operator<<(LogWriter w, bool b);
+QBS_EXPORT LogWriter operator<<(LogWriter w, const MessageTag &tag);
+
+class QBS_EXPORT Logger
+{
+public:
+ Logger(ILogSink *logSink = 0);
+
+ ILogSink *logSink() const { return m_logSink; }
+
+ bool debugEnabled() const;
+ bool traceEnabled() const;
+
+ void printWarning(const ErrorInfo &warning) { logSink()->printWarning(warning); }
+
+ LogWriter qbsLog(LoggerLevel level, bool force = false) const;
+ LogWriter qbsWarning() const { return qbsLog(LoggerWarning); }
+ LogWriter qbsInfo() const { return qbsLog(LoggerInfo); }
+ LogWriter qbsDebug() const { return qbsLog(LoggerDebug); }
+ LogWriter qbsTrace() const { return qbsLog(LoggerTrace); }
+
+private:
+ ILogSink *m_logSink;
+};
+
+
+class TimedActivityLogger
+{
+public:
+ TimedActivityLogger(const Logger &logger, const QString &activity,
+ const QString &prefix = QString(), LoggerLevel logLevel = LoggerDebug,
+ bool alwaysLog = false);
+ void finishActivity();
+ ~TimedActivityLogger();
+
+private:
+ class TimedActivityLoggerPrivate;
+ TimedActivityLoggerPrivate *d;
+};
+
+} // namespace Internal
+} // namespace qbs
+
+#endif // QBS_LOGGER_H
diff --git a/src/lib/corelib/logging/logging.pri b/src/lib/corelib/logging/logging.pri
new file mode 100644
index 000000000..8c0367779
--- /dev/null
+++ b/src/lib/corelib/logging/logging.pri
@@ -0,0 +1,14 @@
+HEADERS += \
+ $$PWD/logger.h \
+ $$PWD/translator.h \
+ $$PWD/ilogsink.h
+
+SOURCES += \
+ $$PWD/logger.cpp \
+ $$PWD/ilogsink.cpp
+
+!qbs_no_dev_install {
+ logging_headers.files = $$PWD/ilogsink.h
+ logging_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/logging
+ INSTALLS += logging_headers
+}
diff --git a/src/lib/corelib/logging/translator.h b/src/lib/corelib/logging/translator.h
new file mode 100644
index 000000000..5c1f5304b
--- /dev/null
+++ b/src/lib/corelib/logging/translator.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#ifndef QBS_TRANSLATOR_H
+#define QBS_TRANSLATOR_H
+
+#include <tools/qbs_export.h>
+
+#include <QCoreApplication>
+
+namespace qbs {
+namespace Internal {
+
+class QBS_EXPORT Tr // Name intended to be short. Exported for use by command line tools.
+{
+ Q_DECLARE_TR_FUNCTIONS(Qbs)
+};
+
+} // namespace Internal
+} // namespace qbs
+
+#endif // QBS_TRANSLATOR_H