Add a startup logger to the runtime to aid with debugging.

This commit is contained in:
Akshay Joshi 2018-09-14 14:41:52 +01:00 committed by Dave Page
parent 0ec3224212
commit 026969e3d1
5 changed files with 141 additions and 3 deletions

59
runtime/Logger.cpp Normal file
View File

@ -0,0 +1,59 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// Logger.cpp - Logger Utility
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin4.h"
#include "Logger.h"
Logger* Logger::m_pThis = NULL;
QString Logger::m_sFileName = "";
QFile* Logger::m_Logfile = NULL;
Logger::Logger()
{
}
Logger::~Logger()
{
}
Logger* Logger::GetLogger()
{
if (m_pThis == NULL)
{
m_pThis = new Logger();
m_sFileName = QDir::homePath() + (QString("/.%1.startup.log").arg(PGA_APP_NAME)).remove(" ");
m_Logfile = new QFile;
m_Logfile->setFileName(m_sFileName);
m_Logfile->open(QIODevice::WriteOnly | QIODevice::Text);
m_Logfile->setPermissions(QFile::ReadOwner|QFile::WriteOwner);
}
return m_pThis;
}
void Logger::Log(const QString& sMessage)
{
QString text = QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss ") + sMessage + "\n";
if (m_Logfile != NULL)
{
QTextStream out(m_Logfile);
out << text;
}
}
void Logger::ReleaseLogger()
{
if (m_pThis != NULL)
{
if(m_Logfile != NULL)
m_Logfile->close();
delete m_pThis;
m_pThis = NULL;
}
}

34
runtime/Logger.h Normal file
View File

@ -0,0 +1,34 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// Logger.h - Logger Utility
//
//////////////////////////////////////////////////////////////////////////
#ifndef LOGGER_H
#define LOGGER_H
#include <QObject>
class Logger : public QObject
{
public:
static Logger* GetLogger();
static void ReleaseLogger();
void Log(const QString& sMessage);
private:
Logger();
virtual ~Logger();
private:
static Logger* m_pThis;
static QString m_sFileName;
static QFile *m_Logfile;
};
#endif // LOGGER_H

View File

@ -10,6 +10,7 @@
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin4.h"
#include "Logger.h"
// Must be before QT
#include <Python.h>
@ -175,6 +176,10 @@ Server::Server(quint16 port, QString key, QString logFileName)
qDebug() << "Python path: " << python_path
<< "\nPython Home: " << pythonHome;
Logger::GetLogger()->Log(QString("Python Path: %1").arg(python_path));
Logger::GetLogger()->Log(QString("Python Home: %1").arg(pythonHome));
if (!pythonHome.isEmpty())
{
pythonHome_utf8 = pythonHome.toUtf8();
@ -190,12 +195,15 @@ Server::Server(quint16 port, QString key, QString logFileName)
#endif
}
Logger::GetLogger()->Log("Initializing Python...");
Py_Initialize();
Logger::GetLogger()->Log("Python initialized.");
// Get the current path
PyObject* sysPath = PySys_GetObject((char*)"path");
// Add new additional path elements
Logger::GetLogger()->Log("Adding new additional path elements");
for (i = path_list.size() - 1; i >= 0 ; --i)
{
#ifdef PYTHON2
@ -210,6 +218,7 @@ Server::Server(quint16 port, QString key, QString logFileName)
}
// Redirect stderr
Logger::GetLogger()->Log("Redirecting stderr...");
PyObject *sys = PyImport_ImportModule("sys");
#ifdef PYTHON2
PyObject *err = PyFile_FromString(m_logFileName.toUtf8().data(), (char *)"w");
@ -263,12 +272,14 @@ bool Server::Init()
if (QFile::exists(m_appfile))
{
qDebug() << "Webapp path: " << m_appfile;
Logger::GetLogger()->Log(QString("Webapp Path: %1").arg(m_appfile));
break;
}
}
if (!QFile::exists(m_appfile))
{
Logger::GetLogger()->Log("Failed to locate pgAdmin4.py, terminating server thread.");
setError(tr("Failed to locate pgAdmin4.py, terminating server thread."));
return false;
}
@ -279,14 +290,17 @@ bool Server::Init()
void Server::run()
{
// Open the application code and run it.
Logger::GetLogger()->Log("Open the application code and run it.");
FILE *cp = fopen(m_appfile.toUtf8().data(), "r");
if (!cp)
{
Logger::GetLogger()->Log(QString(tr("Failed to open the application file: %1, server thread exiting.")).arg(m_appfile));
setError(QString(tr("Failed to open the application file: %1, server thread exiting.")).arg(m_appfile));
return;
}
// Set the port number and key, and force SERVER_MODE off.
Logger::GetLogger()->Log("Set the port number and key, and force SERVER_MODE off");
PyRun_SimpleString(QString("PGADMIN_PORT = %1").arg(m_port).toLatin1());
PyRun_SimpleString(QString("PGADMIN_KEY = '%1'").arg(m_key).toLatin1());
PyRun_SimpleString(QString("SERVER_MODE = False").toLatin1());
@ -303,10 +317,14 @@ void Server::run()
char* n_argv[] = { m_appfile_utf8.data() };
PySys_SetArgv(1, n_argv);
Logger::GetLogger()->Log("Server::run: PyRun_SimpleFile launching application server...");
PyObject* PyFileObject = PyFile_FromString(m_appfile_utf8.data(), (char *)"r");
int ret = PyRun_SimpleFile(PyFile_AsFile(PyFileObject), m_appfile_utf8.data());
if (ret != 0)
{
Logger::GetLogger()->Log("Failed to launch the application server, server thread exiting.");
setError(tr("Failed to launch the application server, server thread exiting."));
}
#else
/*
* Untrusted search path vulnerability in the PySys_SetArgv API function in Python 2.6 and earlier, and possibly later
@ -321,8 +339,12 @@ void Server::run()
wchar_t* n_argv[] = { wcAppName };
PySys_SetArgv(1, n_argv);
Logger::GetLogger()->Log("Server::run: PyRun_SimpleFile launching application server...");
if (PyRun_SimpleFile(cp, m_appfile_utf8.data()) != 0)
{
Logger::GetLogger()->Log("Failed to launch the application server, server thread exiting.");
setError(tr("Failed to launch the application server, server thread exiting."));
}
#endif
fclose(cp);

View File

@ -36,6 +36,7 @@
#include "TrayIcon.h"
#include "MenuActions.h"
#include "FloatingWindow.h"
#include "Logger.h"
#include <QTime>
@ -217,6 +218,7 @@ int main(int argc, char * argv[])
menuActions->setLogFile(logFileName);
splash->showMessage(QString(QWidget::tr("Checking for system tray...")), Qt::AlignBottom | Qt::AlignCenter);
Logger::GetLogger()->Log("Checking for system tray...");
// Check system tray is available or not. If not then create one floating window.
FloatingWindow *floatingWindow = NULL;
@ -235,13 +237,15 @@ int main(int argc, char * argv[])
else
{
splash->showMessage(QString(QWidget::tr("System tray not found, creating floating window...")), Qt::AlignBottom | Qt::AlignCenter);
Logger::GetLogger()->Log("System tray not found, creating floating window...");
// Unable to find tray icon, so creating floting window
floatingWindow = new FloatingWindow();
if (floatingWindow == NULL)
{
QString error = QString(QWidget::tr("Unable to initialize either a tray icon or control window."));
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
Logger::GetLogger()->Log(error);
Logger::ReleaseLogger();
exit(1);
}
@ -256,8 +260,11 @@ int main(int argc, char * argv[])
bool done = false;
splash->showMessage(QString(QWidget::tr("Starting pgAdmin4 server...")), Qt::AlignBottom | Qt::AlignCenter);
Logger::GetLogger()->Log("Starting pgAdmin4 server...");
while (done != true)
{
QString msg = QString(QWidget::tr("Initializing server object, port:%1, key:%2, logfile:%3")).arg(port).arg(key).arg(logFileName);
Logger::GetLogger()->Log(msg);
server = new Server(port, key, logFileName);
if (!server->Init())
@ -269,9 +276,13 @@ int main(int argc, char * argv[])
QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
Logger::GetLogger()->Log(error);
Logger::ReleaseLogger();
exit(1);
}
Logger::GetLogger()->Log("Starting Server Thread...");
server->start();
// This is a hack to give the server a chance to start and potentially fail. As
@ -290,6 +301,7 @@ int main(int argc, char * argv[])
QString error = QString(QWidget::tr("An error occurred initialising the application server:\n\n%1")).arg(server->getError());
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
Logger::GetLogger()->Log(error);
// Allow the user to tweak the Python Path if needed
bool ok;
@ -315,6 +327,7 @@ int main(int argc, char * argv[])
}
else
{
Logger::ReleaseLogger();
exit(1);
}
@ -329,6 +342,7 @@ int main(int argc, char * argv[])
// Generate the app server URL
QString appServerUrl = QString("http://127.0.0.1:%1/?key=%2").arg(port).arg(key);
Logger::GetLogger()->Log(QString(QWidget::tr("Application Server URL: %1")).arg(appServerUrl));
// Read the server connection timeout from the registry or set the default timeout.
int timeout = settings.value("ConnectionTimeout", 30).toInt();
@ -339,6 +353,7 @@ int main(int argc, char * argv[])
QTime endTime = QTime::currentTime().addSecs(timeout);
bool alive = false;
Logger::GetLogger()->Log("The server should be up, we'll attempt to connect and get a response. Ping the server");
while(QTime::currentTime() <= endTime)
{
alive = PingServer(QUrl(appServerUrl));
@ -352,12 +367,14 @@ int main(int argc, char * argv[])
}
// Attempt to connect one more time in case of a long network timeout while looping
Logger::GetLogger()->Log("Attempt to connect one more time in case of a long network timeout while looping");
if (!alive && !PingServer(QUrl(appServerUrl)))
{
splash->finish(NULL);
QString error(QWidget::tr("The application server could not be contacted."));
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
Logger::ReleaseLogger();
exit(1);
}
@ -392,6 +409,8 @@ int main(int argc, char * argv[])
QString error(QWidget::tr("Failed to open the system default web browser. Is one installed?."));
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
Logger::GetLogger()->Log(error);
Logger::ReleaseLogger();
exit(1);
}
}
@ -402,6 +421,8 @@ int main(int argc, char * argv[])
if (floatingWindow != NULL)
floatingWindow->show();
Logger::GetLogger()->Log("Everything works fine, successfully started pgAdmin4.");
Logger::ReleaseLogger();
return app.exec();
}

View File

@ -93,14 +93,16 @@ HEADERS = Server.h \
TrayIcon.h \
LogWindow.h \
MenuActions.h \
FloatingWindow.h
FloatingWindow.h \
Logger.h
SOURCES = pgAdmin4.cpp \
Server.cpp \
ConfigWindow.cpp \
TrayIcon.cpp \
LogWindow.cpp \
MenuActions.cpp \
FloatingWindow.cpp
FloatingWindow.cpp \
Logger.cpp
FORMS = ConfigWindow.ui \
LogWindow.ui \
FloatingWindow.ui