summaryrefslogtreecommitdiff
path: root/ext/Log4Qt/src/logmanager.cpp
diff options
context:
space:
mode:
authorTomasz Sterna <tomek@xiaoka.com>2014-07-11 21:06:39 +0200
committerTomasz Sterna <tomek@xiaoka.com>2014-07-11 21:06:39 +0200
commitefb33d6494d88c27c8766553b6a963ddf2654458 (patch)
tree76dd5e56b79191074998c0fb6bf7b81276116a4b /ext/Log4Qt/src/logmanager.cpp
parent072da88eee57e5d16f0b75c7b90c8a0bc6a60cb3 (diff)
Included Log4Qt in project
Diffstat (limited to 'ext/Log4Qt/src/logmanager.cpp')
-rwxr-xr-xext/Log4Qt/src/logmanager.cpp458
1 files changed, 458 insertions, 0 deletions
diff --git a/ext/Log4Qt/src/logmanager.cpp b/ext/Log4Qt/src/logmanager.cpp
new file mode 100755
index 0000000..5d47c6f
--- /dev/null
+++ b/ext/Log4Qt/src/logmanager.cpp
@@ -0,0 +1,458 @@
+/******************************************************************************
+ *
+ * package: Log4Qt
+ * file: logmanager.cpp
+ * created: September 2007
+ * author: Martin Heinrich
+ *
+ *
+ * changes: Sep 2008, Martin Heinrich:
+ * - Resolved compilation problem with Microsoft Visual Studio 2005
+ * Feb 2009, Martin Heinrich
+ * - Fixed VS 2008 unreferenced formal parameter warning by using
+ * Q_UNUSED in operator<<.
+ *
+ *
+ * Copyright 2007 - 2009 Martin Heinrich
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+
+
+/******************************************************************************
+ * Dependencies
+ ******************************************************************************/
+
+
+#include "logmanager.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QMutex>
+#include <QtCore/QSettings>
+#include <QtCore/QStringList>
+#include "consoleappender.h"
+#include "helpers/datetime.h"
+#include "helpers/initialisationhelper.h"
+#include "helpers/optionconverter.h"
+#include "hierarchy.h"
+#include "propertyconfigurator.h"
+#include "ttcclayout.h"
+#include "varia/denyallfilter.h"
+#include "varia/levelrangefilter.h"
+
+
+namespace Log4Qt
+{
+
+
+ /**************************************************************************
+ * Declarations
+ **************************************************************************/
+
+
+
+ /**************************************************************************
+ * C helper functions
+ **************************************************************************/
+
+
+ LOG4QT_DECLARE_STATIC_LOGGER(static_logger, Log4Qt::LogManager)
+ LOG4QT_GLOBAL_STATIC(QMutex, singleton_guard)
+
+
+
+ /**************************************************************************
+ * Class implementation: LogManager
+ **************************************************************************/
+
+
+ LogManager::LogManager() :
+ mObjectGuard(QMutex::Recursive), // Recursive for doStartup() to call doConfigureLogLogger()
+ mpLoggerRepository(new Hierarchy()),
+ mHandleQtMessages(false),
+ mOldQtMsgHandler(0)
+ {
+ }
+
+
+ LogManager::~LogManager()
+ {
+ static_logger()->warn("Unexpected destruction of LogManager");
+
+ // doSetConfigureHandleQtMessages(false);
+ // delete mpLoggerRepository;
+ }
+
+
+ Logger *LogManager::rootLogger()
+ {
+ return instance()->mpLoggerRepository->rootLogger();
+ }
+
+
+ QList<Logger*> LogManager::loggers()
+ {
+ return instance()->mpLoggerRepository->loggers();
+ }
+
+
+ Level LogManager::threshold()
+ {
+ return instance()->mpLoggerRepository->threshold();
+ }
+
+
+ void LogManager::setThreshold(Level level)
+ {
+ instance()->mpLoggerRepository->setThreshold(level);
+ }
+
+
+ bool LogManager::exists(const char *pName)
+ {
+ return instance()->mpLoggerRepository->exists(QLatin1String(pName));
+ }
+
+
+ LogManager *LogManager::instance()
+ {
+ // Do not use LOG4QT_GLOBAL_STATIC. The LogManager is rather expensive
+ // to construct, an exit handler must be set and doStartup must be
+ // called.
+
+ if (!mspInstance)
+ {
+ QMutexLocker locker(singleton_guard());
+ if (!mspInstance)
+ {
+ mspInstance = new LogManager;
+ // qAddPostRoutine(shutdown);
+ atexit(shutdown);
+ mspInstance->doConfigureLogLogger();
+ mspInstance->welcome();
+ mspInstance->doStartup();
+ }
+ }
+ return mspInstance;
+ }
+
+
+ Logger *LogManager::logger(const QString &rName)
+ {
+ return instance()->mpLoggerRepository->logger(rName);
+ }
+
+
+ void LogManager::resetConfiguration()
+ {
+ setHandleQtMessages(false);
+ instance()->mpLoggerRepository->resetConfiguration();
+ configureLogLogger();
+ }
+
+
+ const char* LogManager::version()
+ {
+ return LOG4QT_VERSION_STR;
+ }
+
+
+ void LogManager::shutdown()
+ {
+ instance()->mpLoggerRepository->shutdown();
+ }
+
+
+ void LogManager::doSetHandleQtMessages(bool handleQtMessages)
+ {
+ QMutexLocker locker(&mObjectGuard);
+
+ if (instance()->mHandleQtMessages == handleQtMessages)
+ return;
+
+ instance()->mHandleQtMessages = handleQtMessages;
+ if (instance()->mHandleQtMessages)
+ {
+ static_logger()->trace("Activate Qt message handling");
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ instance()->mOldQtMsgHandler = qInstallMsgHandler(qtMessageHandler);
+#else
+ instance()->mOldQtMsgHandler = qInstallMessageHandler(qtMessageHandler);
+#endif
+
+ }
+ else
+ {
+ static_logger()->trace("Deactivate Qt message handling");
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ qInstallMsgHandler(instance()->mOldQtMsgHandler);
+#else
+ qInstallMessageHandler(instance()->mOldQtMsgHandler);
+#endif
+ }
+ }
+
+
+ void LogManager::doConfigureLogLogger()
+ {
+ QMutexLocker locker(&instance()->mObjectGuard);
+
+ // Level
+ QString value = InitialisationHelper::setting(QLatin1String("Debug"),
+ QLatin1String("ERROR"));
+ logLogger()->setLevel(OptionConverter::toLevel(value, Level::DEBUG_INT));
+
+ // Common layout
+ TTCCLayout *p_layout = new TTCCLayout();
+ p_layout->setName(QLatin1String("LogLog TTCC"));
+ p_layout->setContextPrinting(false);
+ p_layout->activateOptions();
+
+ // Common deny all filter
+ Filter *p_denyall = new DenyAllFilter();
+ p_denyall->activateOptions();
+
+ // ConsoleAppender on stdout for all events <= INFO
+ ConsoleAppender *p_appender;
+ LevelRangeFilter *p_filter;
+ p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDOUT_TARGET);
+ p_filter = new LevelRangeFilter();
+ p_filter->setNext(p_denyall);
+ p_filter->setLevelMin(Level::NULL_INT);
+ p_filter->setLevelMax(Level::INFO_INT);
+ p_filter->activateOptions();
+ p_appender->setName(QLatin1String("LogLog stdout"));
+ p_appender->addFilter(p_filter);
+ p_appender->activateOptions();
+ logLogger()->addAppender(p_appender);
+
+ // ConsoleAppender on stderr for all events >= WARN
+ p_appender = new ConsoleAppender(p_layout, ConsoleAppender::STDERR_TARGET);
+ p_filter = new LevelRangeFilter();
+ p_filter->setNext(p_denyall);
+ p_filter->setLevelMin(Level::WARN_INT);
+ p_filter->setLevelMax(Level::OFF_INT);
+ p_filter->activateOptions();
+ p_appender->setName(QLatin1String("LogLog stderr"));
+ p_appender->addFilter(p_filter);
+ p_appender->activateOptions();
+ logLogger()->addAppender(p_appender);
+ }
+
+
+ void LogManager::doStartup()
+ {
+ QMutexLocker locker(&instance()->mObjectGuard);
+
+ // Override
+ QString default_value = QLatin1String("false");
+ QString value = InitialisationHelper::setting(QLatin1String("DefaultInitOverride"),
+ default_value);
+ if (value != default_value)
+ {
+ static_logger()->debug("DefaultInitOverride is set. Aborting default initialisation");
+ return;
+ }
+
+ // Configuration using setting Configuration
+ value = InitialisationHelper::setting(QLatin1String("Configuration"));
+ if (QFile::exists(value))
+ {
+ static_logger()->debug("Default initialisation configures from file '%1' specified by Configure", value);
+ PropertyConfigurator::configure(value);
+ return;
+ }
+
+ // Configuration using setting
+ if (QCoreApplication::instance())
+ {
+ const QLatin1String log4qt_group("Log4Qt");
+ const QLatin1String properties_group("Properties");
+ QSettings s;
+ s.beginGroup(log4qt_group);
+ if (s.childGroups().contains(properties_group))
+ {
+ const QString group(QLatin1String("Properties"));
+ static_logger()->debug("Default initialisation configures from setting '%1/%2'", log4qt_group, properties_group);
+ s.beginGroup(properties_group);
+ PropertyConfigurator::configure(s);
+ return;
+ }
+ }
+
+ // Configuration using default file
+ const QString default_file(QLatin1String("log4qt.properties"));
+ if (QFile::exists(default_file))
+ {
+ static_logger()->debug("Default initialisation configures from default file '%1'", default_file);
+ PropertyConfigurator::configure(default_file);
+ return;
+ }
+
+ static_logger()->debug("Default initialisation leaves package unconfigured");
+ }
+
+
+ void LogManager::welcome()
+ {
+ static_logger()->info("Initialising Log4Qt %1",
+ QLatin1String(LOG4QT_VERSION_STR));
+
+ // Debug: Info
+ if (static_logger()->isDebugEnabled())
+ {
+ // Create a nice timestamp with UTC offset
+ DateTime start_time = DateTime::fromMilliSeconds(InitialisationHelper::startTime());
+ QString offset;
+ {
+ QDateTime utc = start_time.toUTC();
+ QDateTime local = start_time.toLocalTime();
+ QDateTime local_as_utc = QDateTime(local.date(), local.time(), Qt::UTC);
+ int min = utc.secsTo(local_as_utc) / 60;
+ if (min < 0)
+ offset += QLatin1Char('-');
+ else
+ offset += QLatin1Char('+');
+ min = abs(min);
+ offset += QString::number(min / 60).rightJustified(2, QLatin1Char('0'));
+ offset += QLatin1Char(':');
+ offset += QString::number(min % 60).rightJustified(2, QLatin1Char('0'));
+ }
+ static_logger()->debug("Program startup time is %1 (UTC%2)",
+ start_time.toString(QLatin1String("ISO8601")),
+ offset);
+ static_logger()->debug("Internal logging uses the level %1",
+ logLogger()->level().toString());
+ }
+
+ // Trace: Dump settings
+ if (static_logger()->isTraceEnabled())
+ {
+ static_logger()->trace("Settings from the system environment:");
+ QString entry;
+ Q_FOREACH (entry, InitialisationHelper::environmentSettings().keys())
+ static_logger()->trace(" %1: '%2'",
+ entry,
+ InitialisationHelper::environmentSettings().value(entry));
+
+ static_logger()->trace("Settings from the application settings:");
+ if (QCoreApplication::instance())
+ {
+ const QLatin1String log4qt_group("Log4Qt");
+ const QLatin1String properties_group("Properties");
+ static_logger()->trace(" %1:", log4qt_group);
+ QSettings s;
+ s.beginGroup(log4qt_group);
+ Q_FOREACH (entry, s.childKeys())
+ static_logger()->trace(" %1: '%2'",
+ entry,
+ s.value(entry).toString());
+ static_logger()->trace(" %1/%2:", log4qt_group, properties_group);
+ s.beginGroup(properties_group);
+ Q_FOREACH (entry, s.childKeys())
+ static_logger()->trace(" %1: '%2'",
+ entry,
+ s.value(entry).toString());
+ } else
+ static_logger()->trace(" QCoreApplication::instance() is not available");
+ }
+ }
+
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
+ void LogManager::qtMessageHandler(QtMsgType type, const char *pMessage)
+ {
+#else
+ void LogManager::qtMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & pMessage)
+ {
+#endif
+ Level level;
+ switch (type)
+ {
+ case QtDebugMsg:
+ level = Level::DEBUG_INT;
+ break;
+ case QtWarningMsg:
+ level = Level::WARN_INT;
+ break;
+ case QtCriticalMsg:
+ level = Level::ERROR_INT;
+ break;
+ case QtFatalMsg:
+ level = Level::FATAL_INT;
+ break;
+ default:
+ level = Level::TRACE_INT;
+ }
+ instance()->qtLogger()->log(level, pMessage);
+
+ // Qt fatal behaviour copied from global.cpp qt_message_output()
+ // begin {
+
+ if ((type == QtFatalMsg) ||
+ ((type == QtWarningMsg) && (!qgetenv("QT_FATAL_WARNINGS").isNull())) )
+ {
+#if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
+ // get the current report mode
+ int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
+ _CrtSetReportMode(_CRT_ERROR, reportMode);
+ int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, QT_VERSION_STR, pMessage);
+ if (ret == 0 && reportMode & _CRTDBG_MODE_WNDW)
+ return; // ignore
+ else if (ret == 1)
+ _CrtDbgBreak();
+#endif
+
+#if defined(Q_OS_UNIX) && defined(QT_DEBUG)
+ abort(); // trap; generates core dump
+#else
+ exit(1); // goodbye cruel world
+#endif
+ }
+
+ // } end
+ }
+
+
+ LogManager *LogManager::mspInstance = 0;
+
+
+
+ /**************************************************************************
+ * Implementation: Operators, Helper
+ **************************************************************************/
+
+
+#ifndef QT_NO_DEBUG_STREAM
+ QDebug operator<<(QDebug debug, const LogManager &rLogManager)
+ {
+ Q_UNUSED(rLogManager); // To avoid warning C4100 on VS 2008
+ QList<Logger *> loggers = rLogManager.loggers();
+ debug.nospace() << "LogManager("
+ << "loggerrepository:" << *rLogManager.loggerRepository()
+ << "log-level:" << rLogManager.logLogger()->level().toString()
+ << "log-appenders:" << rLogManager.logLogger()->appenders().count()
+ << "qt-level:" << rLogManager.qtLogger()->level().toString()
+ << "qt-appenders:" << rLogManager.qtLogger()->appenders().count()
+ << "handleqtmessages:" << rLogManager.handleQtMessages()
+ << ")";
+ return debug.space();
+ }
+#endif // QT_NO_DEBUG_STREAM
+
+
+} // namespace Log4Qt