X-Git-Url: https://vaikene.ee/gitweb/pswgen11.html?a=blobdiff_plain;f=src%2Flibs%2FCommon%2Flogger.cpp;h=94d9fa9eb9e7ea70136ed359960376a9ce844c68;hb=HEAD;hp=01d56876f9caa0e4bbedc53d33be751a7b0a6956;hpb=0957525838e501a4609a15b8d7a765da43362025;p=evaf diff --git a/src/libs/Common/logger.cpp b/src/libs/Common/logger.cpp index 01d5687..94d9fa9 100644 --- a/src/libs/Common/logger.cpp +++ b/src/libs/Common/logger.cpp @@ -3,7 +3,7 @@ * @brief iLogger interface implementation * @author Enar Vaikene * - * Copyright (c) 2011 Enar Vaikene + * Copyright (c) 2011-2019 Enar Vaikene * * This file is part of the eVaf C++ cross-platform application development framework. * @@ -20,6 +20,9 @@ #include "logger.h" #include "iregistry.h" #include "iapp.h" +#include "iconfig.h" +#include "globals.h" +#include "inifile.h" #include "version.h" #include @@ -37,9 +40,9 @@ //------------------------------------------------------------------- -void eVaf::Common::Internal::defFatalMsgHandler(QString const & msg, QString const & source, QString const & where) +[[noreturn]] void eVaf::Common::Internal::defFatalMsgHandler(QString const & msg, QString const & source, QString const & where) { - Q_UNUSED(source); + Q_UNUSED(source) fprintf(stderr, "FATAL ERROR: %s (occurred in %s)\n", qPrintable(msg), qPrintable(where)); @@ -55,10 +58,18 @@ void eVaf::Common::Internal::defFatalMsgHandler(QString const & msg, QString con using namespace eVaf::Common; +namespace +{ + static Internal::Logger * singleton = nullptr; +} + iLogger * iLogger::instance() { - static Internal::Logger singleton; - return &singleton; + if (nullptr == singleton) + { + singleton = new Internal::Logger; + } + return singleton; } @@ -75,35 +86,61 @@ LoggerSource::LoggerSource() LoggerSource::LoggerSource(LoggerSource const & o) : QSharedData() + , name(o.name) , severity(o.severity) + , fileName(o.fileName) , maxSize(o.maxSize) , maxCount(o.maxCount) {} -void LoggerSource::init(QString const & source, QString const & logDir, QString const & etcDir) +void LoggerSource::init(QString const & source) { - Q_UNUSED(etcDir); - - fileName = logDir + source + ".log"; + name = source; + fileName = iApp::instance()->logDir() + source + ".log"; + + // Set default settings + severity = iLogger::Fatal; + maxSize = 100 * 1024; + maxCount = 3; + + // Read settings from the 'logger.ini' file + QString confFileName = iApp::instance()->etcDir() + "logger.ini"; + if (QFile::exists(confFileName)) { + IniFile ini(confFileName, QIODevice::ReadOnly); + + // Default values for all sources + maxSize = 1024 * ini.getValue(".default/log_size", maxSize / 1024).toUInt(); + maxCount = ini.getValue(".default/log_count", maxCount).toUInt(); + + // Default values for this source + maxSize = 1024 * ini.getValue(source.toLatin1() + "/log_size", maxSize / 1024).toUInt(); + maxCount = ini.getValue(source.toLatin1() + "/log_count", maxCount).toUInt(); + } } //------------------------------------------------------------------- -/// Recursively renames backup files -void renameBackupFile(QDir & dir, QString const & baseName, int idx) +namespace { - QString f1 = QString("%1.%2").arg(baseName).arg(idx); - QString f2 = QString("%1.%2").arg(baseName).arg(idx + 1); + /// Recursively renames backup files + void renameBackupFile(QDir & dir, QString const & baseName, int idx) + { + QString f1 = QString("%1.%2").arg(baseName).arg(idx); + QString f2 = QString("%1.%2").arg(baseName).arg(idx + 1); - if (dir.exists(f2)) - renameBackupFile(dir, baseName, idx + 1); + if (dir.exists(f2)) + renameBackupFile(dir, baseName, idx + 1); - dir.rename(f1, f2); + dir.rename(f1, f2); + } } void LoggerWorker::writeToLogFile(LoggerSource const & src, QString const & msg) { + //::printf("writeToLogFile(\'%s\', \'%s\') fileName = \'%s\'\n", qPrintable(src.name), qPrintable(msg), qPrintable(src.fileName)); + if (src.fileName.isEmpty()) + return; QFile f(src.fileName); QFile::OpenMode mode; #ifdef Q_OS_LINUX @@ -142,37 +179,48 @@ void LoggerWorker::writeToLogFile(LoggerSource const & src, QString const & msg) //------------------------------------------------------------------- +void Logger::destroyInstance() +{ + if (singleton != nullptr) + { + delete singleton; + singleton = nullptr; + } +} + Logger::Logger() : iLogger() + , mReady(false) , mFatalMsgHandler(defFatalMsgHandler) , mConsoleSeverity(iLogger::Fatal) - , mDefaultSource("evaf") - , mThread(0) - , mWorker(0) { setObjectName(QString("%1-iLogger").arg(VER_MODULE_NAME_STR)); qRegisterMetaType("LoggerSource"); - write(Info, QString("%1 created").arg(objectName()), 0, printf("%s:%s:%d", __FILE__, __FUNCTION__, __LINE__)); + // Create the default source + mDefaultSource = new LoggerSource; + mDefaultSource->name = "common"; + + write(Info, QString("%1 created").arg(objectName()), QString(), printf("%s:%s:%d", __FILE__, __FUNCTION__, __LINE__)); } Logger::~Logger() { // Disconnect any potential receivers from this object - disconnect(this, SIGNAL(loggerEvent(Common::iLogger::Severity,QString,QString,QString)), 0, 0); + disconnect(this, SIGNAL(loggerEvent(Common::iLogger::Severity,QString,QString,QString)), nullptr, nullptr); // Destroy the worker thread if (mWorker) { - delete mWorker; + mWorker.reset(); if (mThread) { mThread->quit(); mThread->wait(); - delete mThread; + mThread.reset(); } } - write(Info, QString("%1 destroyed").arg(objectName()), 0, printf("%s:%s:%d", __FILE__, __FUNCTION__, __LINE__)); + write(Info, QString("%1 destroyed").arg(objectName()), QString(), printf("%s:%s:%d", __FILE__, __FUNCTION__, __LINE__)); } bool Logger::init() @@ -183,31 +231,50 @@ bool Logger::init() // Clear existing sources in case the application was restarted mSources.clear(); + // Set the default source name to the name of the application + setDefaultSource(iApp::instance()->name()); + + // Read configuration parameters from the application's INI file + QVariant v = iConfig::instance()->getValue(QString("%1/general/log_level").arg(iApp::instance()->name()), severity()); + if (v.isValid()) + setSeverity(iLogger::Severity(qBound(int(iLogger::None), v.toInt(), int(iLogger::Debug)))); + v = iConfig::instance()->getValue(QString("%1/general/log_size").arg(iApp::instance()->name()), maxSize()); + if (v.isValid()) + setMaxSize(v.toUInt()); + v = iConfig::instance()->getValue(QString("%1/general/log_cnt").arg(iApp::instance()->name()), maxCount()); + if (v.isValid()) + setMaxCount(v.toUInt()); + // Destroy the previous worker thread - if (mWorker) { - delete mWorker; - if (mThread) { - mThread->quit(); - mThread->wait(); - delete mThread; - } + if (mThread) { + mThread->quit(); + mThread->wait(); } // Create the worker thread - mWorker = new LoggerWorker; - mThread = new QThread; - mWorker->moveToThread(mThread); + mWorker.reset(new LoggerWorker); + mThread.reset(new QThread); + mWorker->moveToThread(mThread.data()); mThread->start(QThread::IdlePriority); - connect(this, SIGNAL(writeToLogFile(LoggerSource,QString)), mWorker, SLOT(writeToLogFile(LoggerSource,QString)), Qt::QueuedConnection); + connect(this, SIGNAL(writeToLogFile(LoggerSource,QString)), mWorker.data(), SLOT(writeToLogFile(LoggerSource,QString)), Qt::QueuedConnection); - write(Info, QString("%1 initialized").arg(objectName()), 0, printf("%s:%s:%d", __FILE__, __FUNCTION__, __LINE__)); + mReady = true; + + write(Info, QString("%1 initialized").arg(objectName()), QString(), printf("%s:%s:%d", __FILE__, __FUNCTION__, __LINE__)); return true; } +QString Logger::defaultSource() const +{ + return mDefaultSource->name; +} + void Logger::setDefaultSource(QString const & source) { - mDefaultSource = source; + LoggerSource * src = getSource(); + if (src && src->name != source) + getSource(QString())->init(source); } iLogger::Severity Logger::severity(QString const & source) @@ -227,7 +294,7 @@ uint Logger::maxSize(QString const & source) void Logger::setMaxSize(uint maxSize, QString const & source) { - getSource(source)->maxSize = maxSize; + getSource(source)->maxSize = maxSize * 1024; } uint Logger::maxCount(QString const & source) @@ -262,46 +329,30 @@ void Logger::write(Severity severity, QString const & msg, QString const & sourc return; // Write to the log file - LoggerSource * src = getSource(source); - if (severity <= src->severity && src->severity != iLogger::None) { - QString buf; - QTextStream io(&buf); + if (mReady) { + LoggerSource * src = getSource(source); + if (severity <= src->severity && src->severity != iLogger::None) { + QString buf; + QTextStream io(&buf); - // Date/time stamp - io << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); + // Date/time stamp + io << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); - // Severity - io << " " << severityText[severity]; + // Severity + io << " " << severityText[severity]; - // Message - io << msg; + // Message + io << msg; - // Location in the source file - if (!where.isEmpty()) - io << " (occurred in " << where << ")"; + // Location in the source file + if (!where.isEmpty()) + io << " (occurred in " << where << ")"; - io << endl; - io.flush(); + io << endl; + io.flush(); - // If the worker is initialized, use the worker thread to do the job - if (mWorker) { emit writeToLogFile(*src, buf); } - // Otherwise we have to do it ourselves - else { - QFile f(src->fileName); - QFile::OpenMode mode; -#ifdef Q_OS_LINUX - mode = QFile::Append | QFile::Text | QFile::Unbuffered; -#else - mode = QFile::Append | QFile::Text; -#endif - - if (f.open(mode)) { - f.write(buf.toLocal8Bit()); - f.close(); - } - } } // Output to the console @@ -309,25 +360,25 @@ void Logger::write(Severity severity, QString const & msg, QString const & sourc FILE * f = (severity < iLogger::Info) ? stderr : stdout; // Set text colors -#ifdef Q_OS_LINUX +#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS) switch (severity) { case iLogger::Info: - fprintf(f, "\e[32m"); // Green + fprintf(f, "\033[32m"); // Green break; case iLogger::Warning: - fprintf(f, "\e[1m"); // Bold + fprintf(f, "\033[1m"); // Bold break; case iLogger::Error: - fprintf(f, "\e[31m"); // Red + fprintf(f, "\033[31m"); // Red break; case iLogger::Fatal: - fprintf(f, "\e[31m\e[1m"); // Bold Red + fprintf(f, "\033[31m\033[1m"); // Bold Red break; default: - fprintf(f, "\e[34m"); // Blue + fprintf(f, "\033[34m"); // Blue break; } -#elif defined Q_OS_WIN32 +#elif defined(Q_OS_WIN32) switch (severity) { case iLogger::Info: setColor(FOREGROUND_GREEN); @@ -355,9 +406,9 @@ void Logger::write(Severity severity, QString const & msg, QString const & sourc fprintf(f, "\t(occurred in %s)\n\n", qPrintable(where)); // Reset text colors -#ifdef Q_OS_LINUX - fputs("\e[0m", f); -#elif defined Q_OS_WIN32 +#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS) + fputs("\033[0m", f); +#elif defined(Q_OS_WIN32) setColor(7); #endif @@ -378,17 +429,21 @@ QString Logger::printf(char const * const fmt, ...) const #ifdef Q_OS_WIN32 char str[4096]; #else - char * str = 0; + char * str = nullptr; #endif va_list ap; #ifdef Q_OS_WIN32 va_start(ap, fmt); +# ifdef Q_CC_GNU + vsnprintf(str, sizeof(str), fmt, ap); +# else _vsnprintf_s(str, sizeof(str), _TRUNCATE, fmt, ap); +# endif va_end(ap); #else ::va_start(ap, fmt); - if (::vasprintf(&str, fmt, ap)); // IF is needed to avoid the compiler warning + if (::vasprintf(&str, fmt, ap)) {} // IF is needed to avoid the compiler warning ::va_end(ap); #endif @@ -436,6 +491,9 @@ FatalMsgHandler Logger::installFatalMsgHandler(FatalMsgHandler newHandler) LoggerSource * Logger::getSource(QString const & source) { + if (source.isEmpty() || source == mDefaultSource->name) + return mDefaultSource.data(); + QHash >::const_iterator it = mSources.constFind(source); if (it != mSources.constEnd()) return it->data(); @@ -445,7 +503,7 @@ LoggerSource * Logger::getSource(QString const & source) mSources.insert(source, src); // Initialize the new source - src->init(source.isEmpty() ? mDefaultSource : source, iApp::instance()->logDir(), iApp::instance()->etcDir()); + src->init(source); return src.data(); }