1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-01 09:24:10 +01:00

LP-362 make file logging thread safe (and asynchronous)

This commit is contained in:
Philippe Renon 2016-07-21 01:51:08 +02:00
parent 783bb83642
commit 54b33e0a07
3 changed files with 158 additions and 38 deletions

View File

@ -84,6 +84,7 @@
#include "qtsingleapplication.h"
#include "utils/xmlconfig.h"
#include "utils/pathutils.h"
#include "utils/filelogger.h"
#include "gcssplashscreen.h"
#include <extensionsystem/pluginmanager.h>
@ -108,7 +109,6 @@
#include <QSplashScreen>
#include <QSurfaceFormat>
namespace {
typedef QList<ExtensionSystem::PluginSpec *> PluginSpecSet;
typedef QMap<QString, bool> AppOptions;
typedef QMap<QString, QString> AppOptionValues;
@ -286,48 +286,21 @@ void systemInit()
QSurfaceFormat::setDefaultFormat(format);
}
static QTextStream *logStream;
static FileLogger *logger;
void mainMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
Q_UNUSED(context);
QTextStream &out = *logStream;
// logStream << QTime::currentTime().toString("hh:mm:ss.zzz ");
switch (type) {
case QtDebugMsg:
out << "DBG: ";
break;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
case QtInfoMsg:
out << "INF: ";
break;
#endif
case QtWarningMsg:
out << "WRN: ";
break;
case QtCriticalMsg:
out << "CRT: ";
break;
case QtFatalMsg:
out << "FTL: ";
break;
}
out << msg << '\n';
out.flush();
logger->log(type, context, msg);
}
Q_DECLARE_METATYPE(QtMsgType)
void logInit(QString fileName)
{
QFile *file = new QFile(fileName);
if (file->open(QIODevice::WriteOnly | QIODevice::Text)) {
logStream = new QTextStream(file);
qInstallMessageHandler(mainMessageOutput);
} else {
qRegisterMetaType<QtMsgType>();
qInstallMessageHandler(mainMessageOutput);
logger = new FileLogger();
if (!logger->start(fileName)) {
displayError(msgLogfileOpenFailed(fileName));
}
}
@ -456,7 +429,6 @@ void loadTranslators(QString language, QTranslator &translator, QTranslator &qtT
translator.load(QString());
}
}
} // namespace anonymous
int main(int argc, char * *argv)
{
@ -494,6 +466,8 @@ int main(int argc, char * *argv)
if (appOptionValues.contains(LOG_FILE_OPTION)) {
QString logFileName = appOptionValues.value(LOG_FILE_OPTION);
logInit(logFileName);
// relog command line arguments for the benefit of the file logger...
qDebug() << "Command line" << app.arguments();
}
// load user settings
@ -644,5 +618,9 @@ int main(int argc, char * *argv)
qDebug() << "main - GCS ran for" << timer.elapsed() << "ms";
if (logger) {
delete logger;
}
return ret;
}

View File

@ -0,0 +1,141 @@
/**
******************************************************************************
*
* @file filelogger.h
* @author The LibrePilot Project, http://www.openpilot.org Copyright (C) 2016.
* Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup
* @{
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#pragma once
#include "utils_global.h"
#include <QObject>
#include <QFile>
#include <QTextStream>
#include <QThread>
#include <QDebug>
class QTCREATOR_UTILS_EXPORT FileLogger : public QObject {
Q_OBJECT
private:
QTextStream * logStream;
QThread *loggerThread;
bool started;
public:
FileLogger() : QObject(), logStream(NULL), loggerThread(NULL), started(false)
{}
virtual ~FileLogger()
{
stop();
if (logStream) {
delete logStream;
}
}
public:
bool start(const QString &fileName)
{
if (started) {
return false;
}
QFile *file = new QFile(fileName);
if (!file->open(QIODevice::WriteOnly | QIODevice::Text)) {
return false;
}
logStream = new QTextStream(file);
loggerThread = new QThread(this);
moveToThread(loggerThread);
loggerThread->start();
started = true;
return true;
}
bool stop()
{
if (!started) {
return false;
}
// stop accepting messages
started = false;
// make sure all messages are flushed by sending a blocking message
QtMsgType type = QtDebugMsg;
const QString msg = "stopping file logger";
QMetaObject::invokeMethod(this, "doLog", Qt::BlockingQueuedConnection,
Q_ARG(QtMsgType, type), Q_ARG(const QString &, msg));
return true;
}
void log(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
Q_UNUSED(context);
if (!started) {
return;
}
QMetaObject::invokeMethod(this, "doLog", Qt::QueuedConnection,
Q_ARG(QtMsgType, type), Q_ARG(const QString &, msg));
}
private slots:
void doLog(QtMsgType type, const QString &msg)
{
QTextStream &out = *logStream;
// logStream << QTime::currentTime().toString("hh:mm:ss.zzz ");
switch (type) {
case QtDebugMsg:
out << "DBG: ";
break;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
case QtInfoMsg:
out << "INF: ";
break;
#endif
case QtWarningMsg:
out << "WRN: ";
break;
case QtCriticalMsg:
out << "CRT: ";
break;
case QtFatalMsg:
out << "FTL: ";
break;
}
out << msg << '\n';
out.flush();
}
};

View File

@ -121,7 +121,8 @@ HEADERS += \
logfile.h \
crc.h \
mustache.h \
textbubbleslider.h
textbubbleslider.h \
filelogger.h
HEADERS += xmlconfig.h