Request logging

This commit is contained in:
ArsenArsen 2017-08-21 16:17:20 +02:00
parent 4ecade7b2e
commit db24653f7d
13 changed files with 331 additions and 35 deletions

View File

@ -64,7 +64,9 @@ SOURCES += main.cpp\
uploaders/default/imgursettingsdialog.cpp \ uploaders/default/imgursettingsdialog.cpp \
uploaders/default/imgplusuploader.cpp \ uploaders/default/imgplusuploader.cpp \
filenamevalidator.cpp \ filenamevalidator.cpp \
logs/requestlogging.cpp logs/requestlogging.cpp \
logs/historydialog.cpp \
monospacetextdialog.cpp
HEADERS += mainwindow.hpp \ HEADERS += mainwindow.hpp \
cropeditor/cropeditor.hpp \ cropeditor/cropeditor.hpp \
@ -109,7 +111,9 @@ HEADERS += mainwindow.hpp \
uploaders/default/imgursettingsdialog.hpp \ uploaders/default/imgursettingsdialog.hpp \
uploaders/default/imgplusuploader.hpp \ uploaders/default/imgplusuploader.hpp \
filenamevalidator.hpp \ filenamevalidator.hpp \
logs/requestlogging.hpp logs/requestlogging.hpp \
logs/historydialog.h \
monospacetextdialog.h
nopkg { nopkg {
# win32 { # win32 {
@ -161,7 +165,9 @@ FORMS += mainwindow.ui \
settingsdialog.ui \ settingsdialog.ui \
aboutbox.ui \ aboutbox.ui \
hotkeyinputdialog.ui \ hotkeyinputdialog.ui \
uploaders/default/imgursettingsdialog.ui uploaders/default/imgursettingsdialog.ui \
logs/historydialog.ui \
monospacetextdialog.ui
DISTFILES += \ DISTFILES += \
README.md \ README.md \

View File

@ -3,9 +3,19 @@
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
#include <QNetworkRequest> #include <QNetworkRequest>
#include <logs/requestlogging.hpp>
QNetworkAccessManager ioutils::networkManager; QNetworkAccessManager ioutils::networkManager;
void addLogEntry(QNetworkReply *reply, QByteArray data) {
requestlogging::RequestContext ctx;
ctx.reply = reply;
ctx.response = data;
requestlogging::addEntry(ctx);
}
void ioutils::postMultipart(QUrl target, void ioutils::postMultipart(QUrl target,
QList<QPair<QString, QString>> headers, QList<QPair<QString, QString>> headers,
QHttpMultiPart *body, QHttpMultiPart *body,
@ -17,6 +27,7 @@ void ioutils::postMultipart(QUrl target,
QNetworkReply *reply = networkManager.post(req, body); QNetworkReply *reply = networkManager.post(req, body);
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] { QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
addLogEntry(reply, data);
callback(QJsonDocument::fromJson(data), data, reply); callback(QJsonDocument::fromJson(data), data, reply);
delete reply; delete reply;
}); });
@ -32,7 +43,9 @@ void ioutils::postMultipartData(QUrl target,
} }
QNetworkReply *reply = networkManager.post(req, body); QNetworkReply *reply = networkManager.post(req, body);
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] { QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
callback(reply->readAll(), reply); QByteArray data = reply->readAll();
addLogEntry(reply, data);
callback(data, reply);
delete reply; delete reply;
}); });
} }
@ -47,6 +60,7 @@ void ioutils::getJson(QUrl target,
QNetworkReply *reply = networkManager.get(req); QNetworkReply *reply = networkManager.get(req);
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] { QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
addLogEntry(reply, data);
callback(QJsonDocument::fromJson(data), data, reply); callback(QJsonDocument::fromJson(data), data, reply);
reply->deleteLater(); reply->deleteLater();
}); });
@ -63,6 +77,7 @@ void ioutils::postJson(QUrl target,
QNetworkReply *reply = networkManager.post(req, body); QNetworkReply *reply = networkManager.post(req, body);
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] { QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
addLogEntry(reply, data);
callback(QJsonDocument::fromJson(data), data, reply); callback(QJsonDocument::fromJson(data), data, reply);
delete reply; delete reply;
}); });
@ -75,7 +90,9 @@ void ioutils::getData(QUrl target, QList<QPair<QString, QString>> headers, std::
} }
QNetworkReply *reply = networkManager.get(req); QNetworkReply *reply = networkManager.get(req);
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] { QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
callback(reply->readAll(), reply); QByteArray data = reply->readAll();
addLogEntry(reply, data);
callback(data, reply);
delete reply; delete reply;
}); });
} }
@ -90,7 +107,9 @@ void ioutils::postData(QUrl target,
} }
QNetworkReply *reply = networkManager.post(req, body); QNetworkReply *reply = networkManager.post(req, body);
QObject::connect(reply, &QNetworkReply::finished, [reply, callback] { QObject::connect(reply, &QNetworkReply::finished, [reply, callback] {
callback(reply->readAll(), reply); QByteArray data = reply->readAll();
addLogEntry(reply, data);
callback(data, reply);
delete reply; delete reply;
}); });
} }

37
logs/historydialog.cpp Normal file
View File

@ -0,0 +1,37 @@
#include "historydialog.h"
#include "requestlogging.hpp"
#include "ui_historydialog.h"
#include <monospacetextdialog.h>
using requestlogging::LoggedRequest;
HistoryDialog::HistoryDialog(QWidget *parent) : QDialog(parent), ui(new Ui::HistoryDialog) {
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
ui->treeWidget->setColumnWidth(0, 50);
ui->treeWidget->setColumnWidth(1, 150);
ui->treeWidget->setColumnWidth(2, 50);
ui->treeWidget->setColumnWidth(3, 100);
QList<LoggedRequest> requests = requestlogging::getRequests();
for (LoggedRequest req : requests) {
ui->treeWidget->addTopLevelItem(new QTreeWidgetItem(
{ req.getType(), req.getUrl(), QString::number(req.getResponseCode()), req.getTime() + " UTC" }));
}
}
HistoryDialog::~HistoryDialog() {
delete ui;
}
void HistoryDialog::on_treeWidget_doubleClicked(const QModelIndex &) {
QString file = ui->treeWidget->currentItem()->text(3);
file = settings::dir().absoluteFilePath("responses/" + file.left(file.length() - 4));
QFile dataFile(file);
if (!dataFile.open(QIODevice::ReadOnly)) return;
MonospaceTextDialog *dialog = new MonospaceTextDialog(file, dataFile.readAll());
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
}

24
logs/historydialog.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef HISTORYDIALOG_H
#define HISTORYDIALOG_H
#include <QDialog>
namespace Ui {
class HistoryDialog;
}
class HistoryDialog : public QDialog {
Q_OBJECT
public:
explicit HistoryDialog(QWidget *parent = 0);
~HistoryDialog();
private slots:
void on_treeWidget_doubleClicked(const QModelIndex &);
private:
Ui::HistoryDialog *ui;
};
#endif // HISTORYDIALOG_H

88
logs/historydialog.ui Normal file
View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>HistoryDialog</class>
<widget class="QDialog" name="HistoryDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Request History</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeWidget" name="treeWidget">
<column>
<property name="text">
<string>Type</string>
</property>
</column>
<column>
<property name="text">
<string>URL</string>
</property>
</column>
<column>
<property name="text">
<string>Status</string>
</property>
</column>
<column>
<property name="text">
<string>Time</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>HistoryDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>HistoryDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -13,6 +13,7 @@
QDir responses(settings::dir().absoluteFilePath("responses")); QDir responses(settings::dir().absoluteFilePath("responses"));
QString requestPath = settings::dir().absoluteFilePath("history"); QString requestPath = settings::dir().absoluteFilePath("history");
void requestlogging::addEntry(RequestContext context) { void requestlogging::addEntry(RequestContext context) {
if (!responses.exists()) responses.mkpath("."); if (!responses.exists()) responses.mkpath(".");
QString timeNow = QDateTime::currentDateTime().toUTC().toString("yyyy-MM-dd HH-mm-ss-zzz"); QString timeNow = QDateTime::currentDateTime().toUTC().toString("yyyy-MM-dd HH-mm-ss-zzz");
@ -29,14 +30,15 @@ void requestlogging::addEntry(RequestContext context) {
return; return;
} }
for (auto header : context.reply->rawHeaderList()) responseFile.write(header + "\n"); for (auto header : context.reply->rawHeaderList())
responseFile.write(header + ": " + context.reply->rawHeader(header) + "\n");
responseFile.write("\n\n" + context.response); responseFile.write("\n\n" + context.response);
responseFile.close(); responseFile.close();
QTextStream(&requestFile) << ioutils::methodString(context.reply->operation()) << " " // $type QTextStream(&requestFile) << ioutils::methodString(context.reply->operation()) << " " // $type
<< context.reply->url().toString() << " " // $url << context.reply->url().toString() << " " // $url
<< context.reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() // $status << context.reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() << " " // $status
<< timeNow; // $time << timeNow.replace(" ", "_"); // $time
requestFile.close(); requestFile.close();
} }
@ -46,6 +48,7 @@ QList<LoggedRequest> requestlogging::getRequests() {
QList<LoggedRequest> ret; QList<LoggedRequest> ret;
QFile requestFile(requestPath); QFile requestFile(requestPath);
if (!requestFile.exists() || !requestFile.open(QIODevice::ReadOnly)) return ret;
QByteArray line; QByteArray line;
while ((line = requestFile.readLine()).size() != 0) { while ((line = requestFile.readLine()).size() != 0) {
@ -54,9 +57,8 @@ QList<LoggedRequest> requestlogging::getRequests() {
stream >> r.type; stream >> r.type;
stream >> r.url; stream >> r.url;
stream >> r.responseCode; stream >> r.responseCode;
QString time; stream >> r.time;
stream >> time; r.time = r.time.replace("_", " ");
r.time = QDateTime::fromString(time, "yyyy-MM-dd HH-mm-ss-zzz");
ret.append(r); ret.append(r);
} }

View File

@ -5,14 +5,12 @@
#include <QNetworkReply> #include <QNetworkReply>
#include <settings.hpp> #include <settings.hpp>
struct RequestContext {
QByteArray response;
QString sender;
QNetworkReply *reply;
};
namespace requestlogging { namespace requestlogging {
void addEntry(RequestContext context); struct RequestContext {
QByteArray response;
QNetworkReply *reply;
};
class LoggedRequest { class LoggedRequest {
friend QList<LoggedRequest> getRequests(); friend QList<LoggedRequest> getRequests();
@ -24,24 +22,25 @@ public:
QString getType() { QString getType() {
return type; return type;
} }
QDateTime getTime() { QString getTime() {
return time; return time;
} }
int getResponseCode() { int getResponseCode() {
return responseCode; return responseCode;
} }
QByteArray getResponse() { QByteArray getResponse() {
return QFile(settings::dir().absoluteFilePath("responses/" + time.toString("yyyy-MM-dd HH-mm-ss-zzz"))).readAll(); return QFile(settings::dir().absoluteFilePath("responses/" + time)).readAll();
} }
private: private:
QString url; QString url;
QString type; QString type;
QDateTime time; QString time;
int responseCode; int responseCode;
}; };
QList<LoggedRequest> getRequests(); QList<LoggedRequest> getRequests();
void addEntry(RequestContext context);
} }
#endif // REQUESTLOGGING_HPP #endif // REQUESTLOGGING_HPP

View File

@ -10,6 +10,7 @@
#include <colorpicker/colorpickerscene.hpp> #include <colorpicker/colorpickerscene.hpp>
#include <formats.hpp> #include <formats.hpp>
#include <hotkeying.hpp> #include <hotkeying.hpp>
#include <logs/historydialog.h>
#include <platformbackend.hpp> #include <platformbackend.hpp>
#include <recording/recordingformats.hpp> #include <recording/recordingformats.hpp>
#include <settings.hpp> #include <settings.hpp>
@ -181,3 +182,8 @@ void MainWindow::on_actionActive_window_triggered() {
void MainWindow::on_actionAbort_triggered() { void MainWindow::on_actionAbort_triggered() {
controller->abort(); controller->abort();
} }
void MainWindow::on_history_clicked() {
HistoryDialog *dialog = new HistoryDialog;
dialog->show();
}

View File

@ -30,6 +30,7 @@ private slots:
void on_actionAbout_triggered(); void on_actionAbout_triggered();
void on_actionActive_window_triggered(); void on_actionActive_window_triggered();
void on_actionAbort_triggered(); void on_actionAbort_triggered();
void on_history_clicked();
public: public:
static MainWindow *inst(); static MainWindow *inst();

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>352</width> <width>340</width>
<height>220</height> <height>239</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -25,13 +25,6 @@
</sizepolicy> </sizepolicy>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QPushButton" name="settings">
<property name="text">
<string>Settings</string>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
@ -44,15 +37,30 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="1" column="0" colspan="2">
<widget class="QPushButton" name="settings">
<property name="text">
<string>Settings</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="history">
<property name="text">
<string>Open request history</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QStatusBar" name="statusBar"/>
<widget class="QMenuBar" name="menuBar"> <widget class="QMenuBar" name="menuBar">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>352</width> <width>340</width>
<height>25</height> <height>22</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile"> <widget class="QMenu" name="menuFile">
@ -91,7 +99,6 @@
<addaction name="menuUtilities"/> <addaction name="menuUtilities"/>
<addaction name="menuRecording"/> <addaction name="menuRecording"/>
</widget> </widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionQuit"> <action name="actionQuit">
<property name="text"> <property name="text">
<string>&amp;Quit</string> <string>&amp;Quit</string>

13
monospacetextdialog.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "monospacetextdialog.h"
#include "ui_monospacetextdialog.h"
MonospaceTextDialog::MonospaceTextDialog(QString name, QByteArray data, QWidget *parent)
: QDialog(parent), ui(new Ui::MonospaceTextDialog) {
ui->setupUi(this);
setWindowTitle(name);
ui->textEdit->setText(data);
}
MonospaceTextDialog::~MonospaceTextDialog() {
delete ui;
}

21
monospacetextdialog.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef MONOSPACETEXTDIALOG_H
#define MONOSPACETEXTDIALOG_H
#include <QDialog>
namespace Ui {
class MonospaceTextDialog;
}
class MonospaceTextDialog : public QDialog {
Q_OBJECT
public:
explicit MonospaceTextDialog(QString name, QByteArray data, QWidget *parent = 0);
~MonospaceTextDialog();
private:
Ui::MonospaceTextDialog *ui;
};
#endif // MONOSPACETEXTDIALOG_H

73
monospacetextdialog.ui Normal file
View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MonospaceTextDialog</class>
<widget class="QDialog" name="MonospaceTextDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="textEdit">
<property name="font">
<font>
<family>Monospace</family>
</font>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>MonospaceTextDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>MonospaceTextDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>