Write the debug log to a file within the OSCAR data folder.

Also immediately emit debug messages to console even before the UI is
initialized.

And present a useful error if the OSCAR data folder can't be created.
This commit is contained in:
sawinglogz 2020-07-19 16:36:22 -04:00
parent 6a658b3be0
commit 20dfb666b0
4 changed files with 52 additions and 12 deletions

View File

@ -12,8 +12,6 @@
#include "version.h" #include "version.h"
#include <QDir> #include <QDir>
#define ASSERTS_SUCK
QThreadPool * otherThreadPool = NULL; QThreadPool * otherThreadPool = NULL;
void MyOutputHandler(QtMsgType type, const QMessageLogContext &context, const QString &msgtxt) void MyOutputHandler(QtMsgType type, const QMessageLogContext &context, const QString &msgtxt)
@ -51,11 +49,7 @@ void MyOutputHandler(QtMsgType type, const QMessageLogContext &context, const QS
if (logger && logger->isRunning()) { if (logger && logger->isRunning()) {
logger->append(msg); logger->append(msg);
} }
#ifdef ASSERTS_SUCK fprintf(stderr, "%s\n", msg.toLocal8Bit().constData());
// else {
// fprintf(stderr, "%s\n", msg.toLocal8Bit().data());
// }
#endif
if (type == QtFatalMsg) { if (type == QtFatalMsg) {
abort(); abort();
@ -91,6 +85,25 @@ void LogThread::connectionReady()
qDebug() << "Logging UI initialized"; qDebug() << "Logging UI initialized";
} }
void LogThread::logToFile()
{
QString debugLog = GetLogDir() + "/debug.txt";
rotateLogs(debugLog); // keep a limited set of previous logs
strlock.lock();
m_logFile = new QFile(debugLog);
Q_ASSERT(m_logFile);
if (m_logFile->open(QFile::ReadWrite | QFile::Text)) {
m_logStream = new QTextStream(m_logFile);
}
strlock.unlock();
if (m_logStream) {
qDebug().noquote() << "Logging to" << debugLog;
} else {
qWarning().noquote() << "Unable to open" << debugLog;
}
}
void shutdownLogger() void shutdownLogger()
{ {
if (logger) { if (logger) {
@ -126,7 +139,16 @@ void LogThread::quit() {
strlock.lock(); strlock.lock();
while (!buffer.isEmpty()) { while (!buffer.isEmpty()) {
QString msg = buffer.takeFirst(); QString msg = buffer.takeFirst();
fprintf(stderr, "%s\n", msg.toLocal8Bit().constData()); if (m_logStream) {
*m_logStream << msg << endl;
}
}
if (m_logStream) {
delete m_logStream;
m_logStream = nullptr;
Q_ASSERT(m_logFile);
delete m_logFile;
m_logFile = nullptr;
} }
strlock.unlock(); strlock.unlock();
} }
@ -139,9 +161,12 @@ void LogThread::run()
do { do {
strlock.lock(); strlock.lock();
//int r = receivers(SIGNAL(outputLog(QString()))); //int r = receivers(SIGNAL(outputLog(QString())));
while (connected && !buffer.isEmpty()) { // Wait to flush the buffer until the UI is connected and the log file has been opened.
while (connected && m_logFile && !buffer.isEmpty()) {
QString msg = buffer.takeFirst(); QString msg = buffer.takeFirst();
fprintf(stderr, "%s\n", msg.toLocal8Bit().data()); if (m_logStream) {
*m_logStream << msg << endl;
}
emit outputLog(msg); emit outputLog(msg);
} }
strlock.unlock(); strlock.unlock();
@ -154,6 +179,7 @@ QString GetLogDir()
{ {
static const QString LOG_DIR_NAME = "logs"; static const QString LOG_DIR_NAME = "logs";
Q_ASSERT(!GetAppData().isEmpty()); // If GetLogDir gets called before GetAppData() is valid, this would point at root.
QDir oscarData(GetAppData()); QDir oscarData(GetAppData());
Q_ASSERT(oscarData.exists()); Q_ASSERT(oscarData.exists());
if (!oscarData.exists(LOG_DIR_NAME)) { if (!oscarData.exists(LOG_DIR_NAME)) {

View File

@ -20,7 +20,7 @@ class LogThread:public QObject, public QRunnable
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit LogThread() : QRunnable() { running = false; logtime.start(); connected = false; } explicit LogThread() : QRunnable() { running = false; logtime.start(); connected = false; m_logFile = nullptr; m_logStream = nullptr; }
virtual ~LogThread() {} virtual ~LogThread() {}
void run(); void run();
@ -28,6 +28,7 @@ public:
void appendClean(QString msg); void appendClean(QString msg);
bool isRunning() { return running; } bool isRunning() { return running; }
void connectionReady(); void connectionReady();
void logToFile();
void quit(); void quit();
@ -40,6 +41,8 @@ protected:
volatile bool running; volatile bool running;
QTime logtime; QTime logtime;
bool connected; bool connected;
class QFile* m_logFile;
class QTextStream* m_logStream;
}; };
extern LogThread * logger; extern LogThread * logger;

View File

@ -545,6 +545,16 @@ int main(int argc, char *argv[]) {
} }
} }
// Make sure the data directory exists.
if (!newDir.mkpath(".")) {
QMessageBox::warning(nullptr, QObject::tr("Exiting"),
QObject::tr("Unable to create the OSCAR data folder at")+"\n"+
GetAppData());
return 0;
}
// Begin logging to file now that there's a data folder.
logger->logToFile();
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Initialize preferences system (Don't use p_pref before this point!) // Initialize preferences system (Don't use p_pref before this point!)

View File

@ -500,6 +500,7 @@ lessThan(QT_MAJOR_VERSION,5)|lessThan(QT_MINOR_VERSION,9) {
# Create a debug GUI build by adding "CONFIG+=memdebug" to your qmake command # Create a debug GUI build by adding "CONFIG+=memdebug" to your qmake command
memdebug { memdebug {
CONFIG += debug
!win32 { # add memory checking on Linux and macOS debug builds !win32 { # add memory checking on Linux and macOS debug builds
QMAKE_CFLAGS += -g -Werror -fsanitize=address -fno-omit-frame-pointer -fno-common -fsanitize-address-use-after-scope QMAKE_CFLAGS += -g -Werror -fsanitize=address -fno-omit-frame-pointer -fno-common -fsanitize-address-use-after-scope
lessThan(QT_MAJOR_VERSION,5)|lessThan(QT_MINOR_VERSION,9) { lessThan(QT_MAJOR_VERSION,5)|lessThan(QT_MINOR_VERSION,9) {