mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 18:15:45 -05:00
257 lines
6.3 KiB
C++
257 lines
6.3 KiB
C++
/**
|
|
@file
|
|
@author Stefan Frings
|
|
*/
|
|
|
|
#include "filelogger.h"
|
|
#include <QTime>
|
|
#include <QStringList>
|
|
#include <QThread>
|
|
#include <QtGlobal>
|
|
#include <QFile>
|
|
#include <QTimerEvent>
|
|
#include <QDir>
|
|
#include <QFileInfo>
|
|
#include <stdio.h>
|
|
|
|
using namespace qtwebapp;
|
|
|
|
void FileLogger::refreshSettings()
|
|
{
|
|
mutex.lock();
|
|
|
|
if (useQtSettings) {
|
|
refreshQtSettings();
|
|
} else {
|
|
refreshFileLogSettings();
|
|
}
|
|
|
|
mutex.unlock();
|
|
}
|
|
|
|
void FileLogger::refreshQtSettings()
|
|
{
|
|
// Save old file name for later comparison with new settings
|
|
QString oldFileName = fileName;
|
|
|
|
// Load new config settings
|
|
settings->sync();
|
|
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)
|
|
#else
|
|
if (QDir::isRelativePath(fileName))
|
|
#endif
|
|
{
|
|
QFileInfo configFile(settings->fileName());
|
|
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();
|
|
|
|
// Create new file if the filename has been changed
|
|
if (oldFileName != fileName)
|
|
{
|
|
fprintf(stderr, "FileLogger::refreshQtSettings: Logging to %s\n", qPrintable(fileName));
|
|
close();
|
|
open();
|
|
}
|
|
}
|
|
|
|
void FileLogger::refreshFileLogSettings()
|
|
{
|
|
// Save old file name for later comparison with new settings
|
|
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)) {
|
|
fileName = QFileInfo(QDir::currentPath(), fileName).absoluteFilePath();
|
|
}
|
|
|
|
maxSize = fileLoggerSettings.maxSize;
|
|
maxBackups = fileLoggerSettings.maxBackups;
|
|
msgFormat = fileLoggerSettings.msgFormat;
|
|
timestampFormat = fileLoggerSettings.timestampFormat;
|
|
minLevel = fileLoggerSettings.minLevel;
|
|
bufferSize = fileLoggerSettings.bufferSize;
|
|
|
|
// Create new file if the filename has been changed
|
|
if (oldFileName != 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), fileName(""), useQtSettings(true)
|
|
{
|
|
Q_ASSERT(settings != 0);
|
|
Q_ASSERT(refreshInterval >= 0);
|
|
|
|
this->settings = settings;
|
|
file = 0;
|
|
|
|
if (refreshInterval > 0) {
|
|
refreshTimer.start(refreshInterval, this);
|
|
}
|
|
|
|
flushTimer.start(1000, this);
|
|
|
|
refreshSettings();
|
|
}
|
|
|
|
FileLogger::FileLogger(const FileLoggerSettings& settings, const int refreshInterval, QObject* parent) :
|
|
Logger(parent), fileName(""), useQtSettings(false)
|
|
{
|
|
Q_ASSERT(refreshInterval >= 0);
|
|
|
|
fileLoggerSettings = settings;
|
|
file = 0;
|
|
|
|
if (refreshInterval > 0) {
|
|
refreshTimer.start(refreshInterval, 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)));
|
|
|
|
// Flush error messages immediately, to ensure that no important message
|
|
// gets lost when the program terinates abnormally.
|
|
if (logMessage->getType() >= QtCriticalMsg) {
|
|
file->flush();
|
|
}
|
|
|
|
// Check for success
|
|
if (file->error())
|
|
{
|
|
close();
|
|
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 && useQtSettings) {
|
|
Logger::write(logMessage);
|
|
}
|
|
|
|
}
|
|
|
|
void FileLogger::open()
|
|
{
|
|
if (fileName.isEmpty())
|
|
{
|
|
fprintf(stderr, "FileLogger::open: Name of logFile is empty\n");
|
|
}
|
|
else
|
|
{
|
|
file = new QFile(fileName);
|
|
|
|
if (!file->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text))
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
void FileLogger::rotate()
|
|
{
|
|
fprintf(stderr, "FileLogger::rotate\n");
|
|
// count current number of existing backup files
|
|
int count = 0;
|
|
|
|
forever
|
|
{
|
|
QFile bakFile(QString("%1.%2").arg(fileName).arg(count + 1));
|
|
|
|
if (bakFile.exists()) {
|
|
++count;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Remove all old backup files that exceed the maximum number
|
|
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));
|
|
}
|
|
|
|
// Backup the current logfile
|
|
QFile::rename(fileName, fileName + ".1");
|
|
}
|
|
|
|
void FileLogger::timerEvent(QTimerEvent* event)
|
|
{
|
|
if (!event) {
|
|
return;
|
|
} else if (event->timerId() == refreshTimer.timerId()) {
|
|
refreshSettings();
|
|
}
|
|
else if (event->timerId() == flushTimer.timerId() && file)
|
|
{
|
|
mutex.lock();
|
|
|
|
// Flush the I/O buffer
|
|
file->flush();
|
|
|
|
// Rotate the file if it is too large
|
|
if (maxSize > 0 && file->size() >= maxSize)
|
|
{
|
|
close();
|
|
rotate();
|
|
open();
|
|
}
|
|
|
|
mutex.unlock();
|
|
}
|
|
}
|