From 6556096a63c13da270d29e47f22082b3ccbafd5c Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 12 Nov 2017 02:23:55 +0100 Subject: [PATCH] Implemented optional logging to file --- app/main.cpp | 6 +- logging/filelogger.cpp | 151 ++++++++++++++++--------------- logging/loggerwithfile.cpp | 28 +++++- logging/loggerwithfile.h | 8 +- sdrbase/settings/mainsettings.h | 6 +- sdrbase/settings/preferences.cpp | 28 +++++- sdrbase/settings/preferences.h | 9 +- sdrgui/gui/loggingdialog.cpp | 6 +- sdrgui/gui/loggingdialog.ui | 51 ++++++++++- sdrgui/mainwindow.cpp | 24 ++++- sdrgui/mainwindow.h | 6 +- 11 files changed, 219 insertions(+), 104 deletions(-) diff --git a/app/main.cpp b/app/main.cpp index f2a6f157a..d4d9a43b6 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -21,10 +21,10 @@ #include #include -#include "logger.h" +#include "loggerwithfile.h" #include "mainwindow.h" -static int runQtApplication(int argc, char* argv[], qtwebapp::Logger *logger) +static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *logger) { QApplication a(argc, argv); /* @@ -98,7 +98,7 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::Logger *logger) int main(int argc, char* argv[]) { - qtwebapp::Logger *logger = new qtwebapp::Logger(qApp); + qtwebapp::LoggerWithFile *logger = new qtwebapp::LoggerWithFile(qApp); logger->installMsgHandler(); int res = runQtApplication(argc, argv, logger); qWarning("SDRangel quit."); diff --git a/logging/filelogger.cpp b/logging/filelogger.cpp index b967337e1..d73dada71 100644 --- a/logging/filelogger.cpp +++ b/logging/filelogger.cpp @@ -1,7 +1,7 @@ /** - @file - @author Stefan Frings -*/ + @file + @author Stefan Frings + */ #include "filelogger.h" #include @@ -32,11 +32,12 @@ void FileLogger::refreshSettings() void FileLogger::refreshQtSettings() { // Save old file name for later comparision with new settings - QString oldFileName=fileName; + QString oldFileName = fileName; // Load new config settings settings->sync(); - fileName=settings->value("fileName").toString(); + fileName = settings->value("fileName").toString(); + // Convert relative fileName to absolute, based on the directory of the config file. #ifdef Q_OS_WIN32 if (QDir::isRelativePath(fileName) && settings->format()!=QSettings::NativeFormat) @@ -45,19 +46,20 @@ void FileLogger::refreshQtSettings() #endif { QFileInfo configFile(settings->fileName()); - fileName=QFileInfo(configFile.absolutePath(),fileName).absoluteFilePath(); + fileName = QFileInfo(configFile.absolutePath(), fileName).absoluteFilePath(); } - maxSize=settings->value("maxSize",0).toLongLong(); - maxBackups=settings->value("maxBackups",0).toInt(); - msgFormat=settings->value("msgFormat","{timestamp} {type} {msg}").toString(); - timestampFormat=settings->value("timestampFormat","yyyy-MM-dd hh:mm:ss.zzz").toString(); - minLevel=static_cast(settings->value("minLevel",0).toInt()); - bufferSize=settings->value("bufferSize",0).toInt(); + + maxSize = settings->value("maxSize", 0).toLongLong(); + maxBackups = settings->value("maxBackups", 0).toInt(); + msgFormat = settings->value("msgFormat", "{timestamp} {type} {msg}").toString(); + timestampFormat = settings->value("timestampFormat", "yyyy-MM-dd hh:mm:ss.zzz").toString(); + minLevel = static_cast(settings->value("minLevel", 0).toInt()); + bufferSize = settings->value("bufferSize", 0).toInt(); // Create new file if the filename has been changed - if (oldFileName!=fileName) + if (oldFileName != fileName) { - fprintf(stderr,"Logging to %s\n",qPrintable(fileName)); + fprintf(stderr, "FileLogger::refreshQtSettings: Logging to %s\n", qPrintable(fileName)); close(); open(); } @@ -66,15 +68,13 @@ void FileLogger::refreshQtSettings() void FileLogger::refreshFileLogSettings() { // Save old file name for later comparision with new settings - QString oldFileName = fileLoggerSettings.fileName; + QString oldFileName = fileName; // Load new config settings - fileName = fileLoggerSettings.fileName; // Convert relative fileName to absolute, based on the current working directory - if (QDir::isRelativePath(fileName)) - { + if (QDir::isRelativePath(fileName)) { fileName = QFileInfo(QDir::currentPath(), fileName).absoluteFilePath(); } @@ -88,61 +88,63 @@ void FileLogger::refreshFileLogSettings() // Create new file if the filename has been changed if (oldFileName != fileName) { - fprintf(stderr,"Logging to %s\n",qPrintable(fileName)); + fprintf(stderr, "FileLogger::refreshQtSettings: Logging to new file %s\n", qPrintable(fileName)); close(); open(); } } -FileLogger::FileLogger(QSettings* settings, const int refreshInterval, QObject* parent) - : Logger(parent), useQtSettings(true) +FileLogger::FileLogger(QSettings* settings, const int refreshInterval, QObject* parent) : + Logger(parent), fileName(""), useQtSettings(true) { - Q_ASSERT(settings!=0); - Q_ASSERT(refreshInterval>=0); - this->settings=settings; - file=0; - if (refreshInterval>0) - { - refreshTimer.start(refreshInterval,this); + Q_ASSERT(settings != 0); + Q_ASSERT(refreshInterval >= 0); + + this->settings = settings; + file = 0; + + if (refreshInterval > 0) { + refreshTimer.start(refreshInterval, this); } - flushTimer.start(1000,this); + + flushTimer.start(1000, this); + refreshSettings(); } -FileLogger::FileLogger(const FileLoggerSettings& settings, const int refreshInterval, QObject* parent) - : Logger(parent), useQtSettings(false) +FileLogger::FileLogger(const FileLoggerSettings& settings, const int refreshInterval, QObject* parent) : + Logger(parent), fileName(""), useQtSettings(false) { - Q_ASSERT(refreshInterval>=0); + Q_ASSERT(refreshInterval >= 0); + fileLoggerSettings = settings; - file=0; - if (refreshInterval>0) - { - refreshTimer.start(refreshInterval,this); + file = 0; + + if (refreshInterval > 0) { + refreshTimer.start(refreshInterval, this); } - flushTimer.start(1000,this); + + flushTimer.start(1000, this); + refreshSettings(); } - FileLogger::~FileLogger() { close(); } - void FileLogger::write(const LogMessage* logMessage) { // Try to write to the file if (file) { - // Write the message - file->write(qPrintable(logMessage->toString(msgFormat,timestampFormat))); + file->write(qPrintable(logMessage->toString(msgFormat, timestampFormat))); // Flush error messages immediately, to ensure that no important message // gets lost when the program terinates abnormally. - if (logMessage->getType()>=QtCriticalMsg) - { + if (logMessage->getType() >= QtCriticalMsg) { file->flush(); } @@ -150,14 +152,12 @@ void FileLogger::write(const LogMessage* logMessage) if (file->error()) { close(); - qWarning("Cannot write to log file %s: %s",qPrintable(fileName),qPrintable(file->errorString())); + fprintf(stderr, "FileLogger::write: Cannot write to log file %s: %s\n", qPrintable(fileName), qPrintable(file->errorString())); } - } // Fall-back to the super class method, if writing failed - if (!file) - { + if (!file && useQtSettings) { Logger::write(logMessage); } @@ -167,73 +167,76 @@ void FileLogger::open() { if (fileName.isEmpty()) { - qWarning("Name of logFile is empty"); + fprintf(stderr, "FileLogger::open: Name of logFile is empty\n"); } - else { - file=new QFile(fileName); + else + { + file = new QFile(fileName); + if (!file->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { - qWarning("Cannot open log file %s: %s",qPrintable(fileName),qPrintable(file->errorString())); - file=0; + fprintf(stderr, "FileLogger::open: Cannot open log file %s: %s\n", qPrintable(fileName), qPrintable(file->errorString())); + file = 0; + } + else + { + fprintf(stderr, "FileLogger::open: Opened log file %s\n", qPrintable(fileName)); } } } - void FileLogger::close() { if (file) { file->close(); delete file; - file=0; + file = 0; } } -void FileLogger::rotate() { +void FileLogger::rotate() +{ + fprintf(stderr, "FileLogger::rotate\n"); // count current number of existing backup files - int count=0; + int count = 0; + forever { - QFile bakFile(QString("%1.%2").arg(fileName).arg(count+1)); - if (bakFile.exists()) - { + QFile bakFile(QString("%1.%2").arg(fileName).arg(count + 1)); + + if (bakFile.exists()) { ++count; - } - else - { + } else { break; } } // Remove all old backup files that exceed the maximum number - while (maxBackups>0 && count>=maxBackups) + while (maxBackups > 0 && count >= maxBackups) { QFile::remove(QString("%1.%2").arg(fileName).arg(count)); --count; } // Rotate backup files - for (int i=count; i>0; --i) { - QFile::rename(QString("%1.%2").arg(fileName).arg(i),QString("%1.%2").arg(fileName).arg(i+1)); + for (int i = count; i > 0; --i) + { + QFile::rename(QString("%1.%2").arg(fileName).arg(i), QString("%1.%2").arg(fileName).arg(i + 1)); } // Backup the current logfile - QFile::rename(fileName,fileName+".1"); + QFile::rename(fileName, fileName + ".1"); } - void FileLogger::timerEvent(QTimerEvent* event) { - if (!event) - { + if (!event) { return; - } - else if (event->timerId()==refreshTimer.timerId()) - { + } else if (event->timerId() == refreshTimer.timerId()) { refreshSettings(); } - else if (event->timerId()==flushTimer.timerId() && file) + else if (event->timerId() == flushTimer.timerId() && file) { mutex.lock(); @@ -241,7 +244,7 @@ void FileLogger::timerEvent(QTimerEvent* event) file->flush(); // Rotate the file if it is too large - if (maxSize>0 && file->size()>=maxSize) + if (maxSize > 0 && file->size() >= maxSize) { close(); rotate(); diff --git a/logging/loggerwithfile.cpp b/logging/loggerwithfile.cpp index e3352083d..33faedae8 100644 --- a/logging/loggerwithfile.cpp +++ b/logging/loggerwithfile.cpp @@ -15,9 +15,28 @@ LoggerWithFile::LoggerWithFile(QObject* parent) consoleLogger = new Logger(this); } -void LoggerWithFile::createFileLogger(const FileLoggerSettings& settings, const int refreshInterval) +LoggerWithFile::~LoggerWithFile() { - fileLogger = new FileLogger(settings, refreshInterval, this); + destroyFileLogger(); + delete consoleLogger; +} + +void LoggerWithFile::createOrSetFileLogger(const FileLoggerSettings& settings, const int refreshInterval) +{ + if (!fileLogger) { + fileLogger = new FileLogger(settings, refreshInterval, this); + } else { + fileLogger->setFileLoggerSettings(settings); + } +} + +void LoggerWithFile::destroyFileLogger() +{ + if (fileLogger) + { + delete fileLogger; + fileLogger = 0; + } } void LoggerWithFile::log(const QtMsgType type, const QString& message, const QString &file, const QString &function, const int line) @@ -38,10 +57,13 @@ void LoggerWithFile::clear(const bool buffer, const bool variables) } } -void LoggerWithFile::setMinMessageLevel(QtMsgType& msgLevel) +void LoggerWithFile::setConsoleMinMessageLevel(const QtMsgType& msgLevel) { consoleLogger->setMinMessageLevel(msgLevel); +} +void LoggerWithFile::setFileMinMessageLevel(const QtMsgType& msgLevel) +{ if (fileLogger) { fileLogger->setMinMessageLevel(msgLevel); } diff --git a/logging/loggerwithfile.h b/logging/loggerwithfile.h index 7b0d3af48..589639f66 100644 --- a/logging/loggerwithfile.h +++ b/logging/loggerwithfile.h @@ -26,8 +26,10 @@ class DECLSPEC LoggerWithFile : public Logger { public: LoggerWithFile(QObject *parent = 0); + virtual ~LoggerWithFile(); - void createFileLogger(const FileLoggerSettings& settings, const int refreshInterval=10000); + void createOrSetFileLogger(const FileLoggerSettings& settings, const int refreshInterval=10000); + void destroyFileLogger(); /** Decorate and log the message, if type>=minLevel. @@ -51,6 +53,7 @@ public: bool getUseFileLogger() const { return useFileFlogger; } void setUseFileLogger(bool use) { useFileFlogger = use; } + bool hasFileLogger() const { return fileLogger != 0; } /** * Get a file logger settings copy @@ -64,7 +67,8 @@ public: */ void setFileLoggerSettings(const FileLoggerSettings& settings) { fileLogger->setFileLoggerSettings(settings); } - void setMinMessageLevel(QtMsgType& msgLevel); + void setConsoleMinMessageLevel(const QtMsgType& msgLevel); + void setFileMinMessageLevel(const QtMsgType& msgLevel); private: /** First console logger */ diff --git a/sdrbase/settings/mainsettings.h b/sdrbase/settings/mainsettings.h index 7f6a9e64a..4b9e4a26a 100644 --- a/sdrbase/settings/mainsettings.h +++ b/sdrbase/settings/mainsettings.h @@ -33,10 +33,12 @@ public: float getLatitude() const { return m_preferences.getLatitude(); } float getLongitude() const { return m_preferences.getLongitude(); } - void setMinLogLevel(const QtMsgType& minLogLevel) { m_preferences.setMinLogLevel(minLogLevel); } + void setConsoleMinLogLevel(const QtMsgType& minLogLevel) { m_preferences.setConsoleMinLogLevel(minLogLevel); } + void setFileMinLogLevel(const QtMsgType& minLogLevel) { m_preferences.setFileMinLogLevel(minLogLevel); } void setUseLogFile(bool useLogFile) { m_preferences.setUseLogFile(useLogFile); } void setLogFileName(const QString& value) { m_preferences.setLogFileName(value); } - QtMsgType getMinLogLevel() const { return m_preferences.getMinLogLevel(); } + QtMsgType getConsoleMinLogLevel() const { return m_preferences.getConsoleMinLogLevel(); } + QtMsgType getFileMinLogLevel() const { return m_preferences.getFileMinLogLevel(); } bool getUseLogFile() const { return m_preferences.getUseLogFile(); } const QString& getLogFileName() const { return m_preferences.getLogFileName(); } diff --git a/sdrbase/settings/preferences.cpp b/sdrbase/settings/preferences.cpp index a28d6846e..467444245 100644 --- a/sdrbase/settings/preferences.cpp +++ b/sdrbase/settings/preferences.cpp @@ -17,6 +17,8 @@ void Preferences::resetToDefaults() m_longitude = 0.0; m_useLogFile = false; m_logFileName = "sdrangel.log"; + m_consoleMinLogLevel = QtDebugMsg; + m_fileMinLogLevel = QtDebugMsg; } QByteArray Preferences::serialize() const @@ -29,9 +31,10 @@ QByteArray Preferences::serialize() const s.writeS32(5, m_sourceIndex); s.writeFloat(6, m_latitude); s.writeFloat(7, m_longitude); - s.writeS32(8, (int) m_minLogLevel); + s.writeS32(8, (int) m_consoleMinLogLevel); s.writeBool(9, m_useLogFile); s.writeString(10, m_logFileName); + s.writeS32(11, (int) m_fileMinLogLevel); return s.final(); } @@ -46,7 +49,8 @@ bool Preferences::deserialize(const QByteArray& data) return false; } - if(d.getVersion() == 1) { + if(d.getVersion() == 1) + { d.readString(1, &m_sourceType); d.readString(2, &m_sourceDevice); d.readString(3, &m_audioType); @@ -62,15 +66,29 @@ bool Preferences::deserialize(const QByteArray& data) (tmpInt == (int) QtWarningMsg) || (tmpInt == (int) QtCriticalMsg) || (tmpInt == (int) QtFatalMsg)) { - m_minLogLevel = (QtMsgType) tmpInt; + m_consoleMinLogLevel = (QtMsgType) tmpInt; } else { - m_minLogLevel = QtDebugMsg; + m_consoleMinLogLevel = QtDebugMsg; } d.readBool(9, &m_useLogFile, false); d.readString(10, &m_logFileName, "sdrangel.log"); + + d.readS32(11, &tmpInt, (int) QtDebugMsg); + + if ((tmpInt == (int) QtDebugMsg) || + (tmpInt == (int) QtInfoMsg) || + (tmpInt == (int) QtWarningMsg) || + (tmpInt == (int) QtCriticalMsg) || + (tmpInt == (int) QtFatalMsg)) { + m_fileMinLogLevel = (QtMsgType) tmpInt; + } else { + m_fileMinLogLevel = QtDebugMsg; + } + return true; - } else { + } else + { resetToDefaults(); return false; } diff --git a/sdrbase/settings/preferences.h b/sdrbase/settings/preferences.h index 7f384c992..c58723447 100644 --- a/sdrbase/settings/preferences.h +++ b/sdrbase/settings/preferences.h @@ -28,10 +28,12 @@ public: float getLatitude() const { return m_latitude; } float getLongitude() const { return m_longitude; } - void setMinLogLevel(const QtMsgType& minLogLevel) { m_minLogLevel = minLogLevel; } + void setConsoleMinLogLevel(const QtMsgType& minLogLevel) { m_consoleMinLogLevel = minLogLevel; } + void setFileMinLogLevel(const QtMsgType& minLogLevel) { m_fileMinLogLevel = minLogLevel; } void setUseLogFile(bool useLogFile) { m_useLogFile = useLogFile; } void setLogFileName(const QString& value) { m_logFileName = value; } - QtMsgType getMinLogLevel() const { return m_minLogLevel; } + QtMsgType getConsoleMinLogLevel() const { return m_consoleMinLogLevel; } + QtMsgType getFileMinLogLevel() const { return m_fileMinLogLevel; } bool getUseLogFile() const { return m_useLogFile; } const QString& getLogFileName() const { return m_logFileName; } @@ -46,7 +48,8 @@ protected: float m_latitude; float m_longitude; - QtMsgType m_minLogLevel; + QtMsgType m_consoleMinLogLevel; + QtMsgType m_fileMinLogLevel; bool m_useLogFile; QString m_logFileName; }; diff --git a/sdrgui/gui/loggingdialog.cpp b/sdrgui/gui/loggingdialog.cpp index 68cf19d66..03c151c14 100644 --- a/sdrgui/gui/loggingdialog.cpp +++ b/sdrgui/gui/loggingdialog.cpp @@ -26,7 +26,8 @@ LoggingDialog::LoggingDialog(MainSettings& mainSettings, QWidget* parent) : m_mainSettings(mainSettings) { ui->setupUi(this); - ui->level->setCurrentIndex(msgLevelToIndex(m_mainSettings.getMinLogLevel())); + ui->consoleLevel->setCurrentIndex(msgLevelToIndex(m_mainSettings.getConsoleMinLogLevel())); + ui->fileLevel->setCurrentIndex(msgLevelToIndex(m_mainSettings.getFileMinLogLevel())); ui->logToFile->setChecked(m_mainSettings.getUseLogFile()); ui->logFileNameText->setText(m_mainSettings.getLogFileName()); m_fileName = m_mainSettings.getLogFileName(); @@ -39,7 +40,8 @@ LoggingDialog::~LoggingDialog() void LoggingDialog::accept() { - m_mainSettings.setMinLogLevel(msgLevelFromIndex(ui->level->currentIndex())); + m_mainSettings.setConsoleMinLogLevel(msgLevelFromIndex(ui->consoleLevel->currentIndex())); + m_mainSettings.setFileMinLogLevel(msgLevelFromIndex(ui->fileLevel->currentIndex())); m_mainSettings.setUseLogFile(ui->logToFile->isChecked()); m_mainSettings.setLogFileName(m_fileName); QDialog::accept(); diff --git a/sdrgui/gui/loggingdialog.ui b/sdrgui/gui/loggingdialog.ui index 7274af266..ec05378a9 100644 --- a/sdrgui/gui/loggingdialog.ui +++ b/sdrgui/gui/loggingdialog.ui @@ -23,16 +23,22 @@ - + - Log level + Console log level - + + + + 80 + 0 + + - Choose minimum message severity level for logging + Choose minimum message severity level for logging to console @@ -69,6 +75,43 @@ + + + + File log level + + + + + + + + 80 + 0 + + + + + Debug + + + + + Info + + + + + Warning + + + + + Error + + + + diff --git a/sdrgui/mainwindow.cpp b/sdrgui/mainwindow.cpp index 114ddbdb3..bbd1cd03d 100644 --- a/sdrgui/mainwindow.cpp +++ b/sdrgui/mainwindow.cpp @@ -51,7 +51,7 @@ #include "plugin/pluginapi.h" #include "gui/glspectrum.h" #include "gui/glspectrumgui.h" -#include "logger.h" +#include "loggerwithfile.h" #include "mainwindow.h" #include "ui_mainwindow.h" @@ -61,7 +61,7 @@ MainWindow *MainWindow::m_instance = 0; -MainWindow::MainWindow(qtwebapp::Logger *logger, QWidget* parent) : +MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow), m_settings(), @@ -1157,5 +1157,23 @@ void MainWindow::updateStatus() void MainWindow::setLoggingOpions() { - m_logger->setMinMessageLevel(m_settings.getMinLogLevel()); + m_logger->setConsoleMinMessageLevel(m_settings.getConsoleMinLogLevel()); + + if (m_settings.getUseLogFile()) + { + qtwebapp::FileLoggerSettings fileLoggerSettings; // default values + + if (m_logger->hasFileLogger()) { + fileLoggerSettings = m_logger->getFileLoggerSettings(); // values from file logger if it exists + } + + fileLoggerSettings.fileName = m_settings.getLogFileName(); // put new values + m_logger->createOrSetFileLogger(fileLoggerSettings, 2000); // create file logger if it does not exist and apply settings in any case + } + + if (m_logger->hasFileLogger()) { + m_logger->setFileMinMessageLevel(m_settings.getFileMinLogLevel()); + } + + m_logger->setUseFileLogger(m_settings.getUseLogFile()); } diff --git a/sdrgui/mainwindow.h b/sdrgui/mainwindow.h index 7e5e4d361..4f6c038dc 100644 --- a/sdrgui/mainwindow.h +++ b/sdrgui/mainwindow.h @@ -51,7 +51,7 @@ class PluginInterface; class QWidget; namespace qtwebapp { - class Logger; + class LoggerWithFile; } namespace Ui { @@ -62,7 +62,7 @@ class SDRANGEL_API MainWindow : public QMainWindow { Q_OBJECT public: - explicit MainWindow(qtwebapp::Logger *logger, QWidget* parent = 0); + explicit MainWindow(qtwebapp::LoggerWithFile *logger, QWidget* parent = 0); ~MainWindow(); static MainWindow *getInstance() { return m_instance; } // Main Window is de facto a singleton so this just returns its reference @@ -114,7 +114,7 @@ private: quint64 m_centerFrequency; std::string m_sampleFileName; - qtwebapp::Logger *m_logger; + qtwebapp::LoggerWithFile *m_logger; void loadSettings(); void loadPresetSettings(const Preset* preset, int tabIndex);