sdrangel/logging/filelogger.cpp

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