Implemented optional logging to file

pull/127/head
f4exb 2017-11-12 02:23:55 +01:00
rodzic 4e7e748ce5
commit 6556096a63
11 zmienionych plików z 219 dodań i 104 usunięć

Wyświetl plik

@ -21,10 +21,10 @@
#include <QStyleFactory>
#include <QFontDatabase>
#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.");

Wyświetl plik

@ -1,7 +1,7 @@
/**
@file
@author Stefan Frings
*/
@file
@author Stefan Frings
*/
#include "filelogger.h"
#include <QTime>
@ -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<QtMsgType>(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<QtMsgType>(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();

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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 */

Wyświetl plik

@ -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(); }

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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;
};

Wyświetl plik

@ -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();

Wyświetl plik

@ -23,16 +23,22 @@
<item>
<layout class="QHBoxLayout" name="levelLayout">
<item>
<widget class="QLabel" name="levelLabel">
<widget class="QLabel" name="consoleLevelLabel">
<property name="text">
<string>Log level</string>
<string>Console log level</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="level">
<widget class="QComboBox" name="consoleLevel">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Choose minimum message severity level for logging</string>
<string>Choose minimum message severity level for logging to console</string>
</property>
<item>
<property name="text">
@ -69,6 +75,43 @@
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="fileLevelLabel">
<property name="text">
<string>File log level</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="fileLevel">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<item>
<property name="text">
<string>Debug</string>
</property>
</item>
<item>
<property name="text">
<string>Info</string>
</property>
</item>
<item>
<property name="text">
<string>Warning</string>
</property>
</item>
<item>
<property name="text">
<string>Error</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>

Wyświetl plik

@ -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());
}

Wyświetl plik

@ -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);