diff --git a/README.md b/README.md index 8550f71..cfba180 100644 --- a/README.md +++ b/README.md @@ -411,6 +411,15 @@ Since the Dolphin integration and the Plasmoid are plugins, testing and debuggin See [Testing and debugging Dolphin/KIO plugin with Qt Creator](/fileitemactionplugin/testing.md) and [Testing and debugging Plasma 5 plasmoid with Qt Creator](/plasmoid/testing.md). +### Logging +It is possible to turn on logging of the underlying library by setting environment variables: + +* `LIB_SYNCTHING_CONNECTOR_LOG_ALL`: log everything mentioned in points below +* `LIB_SYNCTHING_CONNECTOR_LOG_API_CALLS`: log calls to Syncthing's REST-API +* `LIB_SYNCTHING_CONNECTOR_LOG_API_REPLIES`: log replies from Syncthing's REST-API (except events) +* `LIB_SYNCTHING_CONNECTOR_LOG_EVENTS`: log events emitted by Syncthing's events REST-API endpoint +* `LIB_SYNCTHING_CONNECTOR_LOG_DIRS_OR_DEVS_RESETTED`: log when directories/devices are internally resetted + ## Planned features The tray is still under development; the following features are under construction or planned: diff --git a/connector/CMakeLists.txt b/connector/CMakeLists.txt index e08a8e3..07fe79c 100644 --- a/connector/CMakeLists.txt +++ b/connector/CMakeLists.txt @@ -98,27 +98,6 @@ if (SYNCTHING_SERVICE_MOCKED) message(WARNING "SyncthingService class will be mocked") endif () -# configure whether events should be logged -option(SYNCTHING_CONNECTION_LOG_SYNCTHING_EVENTS "enables logging event data to stdout (enable only for debugging!)" OFF) -if (SYNCTHING_CONNECTION_LOG_SYNCTHING_EVENTS) - set_property( - SOURCE syncthingconnection.cpp syncthingconnection_requests.cpp - APPEND - PROPERTY COMPILE_DEFINITIONS ${META_PROJECT_VARNAME_UPPER}_LOG_SYNCTHING_EVENTS) - message(WARNING "SyncthingConnection class will log event data to stdout") -endif () - -# configure whether POSTs should be logged -option(SYNCTHING_CONNECTION_LOG_API_CALLS - "enables logging API calls done by the SyncthingConnector (enable only for debugging!)" OFF) -if (SYNCTHING_CONNECTION_LOG_API_CALLS) - set_property( - SOURCE syncthingconnection_requests.cpp - APPEND - PROPERTY COMPILE_DEFINITIONS ${META_PROJECT_VARNAME_UPPER}_LOG_API_CALLS) - message(WARNING "SyncthingConnection class will log API calls data to stdout") -endif () - # include modules to apply configuration include(BasicConfig) include(QtConfig) diff --git a/connector/syncthingconnection.cpp b/connector/syncthingconnection.cpp index b8510c5..d9b1391 100644 --- a/connector/syncthingconnection.cpp +++ b/connector/syncthingconnection.cpp @@ -7,6 +7,8 @@ #include "./syncthingconnectionmockhelpers.h" #endif +#include "resources/config.h" + #include #include @@ -62,12 +64,15 @@ QNetworkAccessManager &networkAccessManager() /*! * \brief Constructs a new instance ready to connect. To establish the connection, call connect(). */ -SyncthingConnection::SyncthingConnection(const QString &syncthingUrl, const QByteArray &apiKey, QObject *parent) +SyncthingConnection::SyncthingConnection( + const QString &syncthingUrl, const QByteArray &apiKey, SyncthingConnectionLoggingFlags loggingFlags, QObject *parent) : QObject(parent) , m_syncthingUrl(syncthingUrl) , m_apiKey(apiKey) , m_status(SyncthingStatus::Disconnected) , m_statusComputionFlags(SyncthingStatusComputionFlags::Default) + , m_loggingFlags(SyncthingConnectionLoggingFlags::None) + , m_loggingFlagsHandler(SyncthingConnectionLoggingFlags::None) , m_keepPolling(false) , m_abortingAllRequests(false) , m_abortingToReconnect(false) @@ -118,16 +123,7 @@ SyncthingConnection::SyncthingConnection(const QString &syncthingUrl, const QByt setupTestData(); #endif -#ifdef LIB_SYNCTHING_CONNECTOR_LOG_SYNCTHING_EVENTS - QObject::connect(this, &SyncthingConnection::newDirs, [](const auto &dirs) { - std::cerr << Phrases::Info << "Directory list renewed:" << Phrases::End; - std::cerr << displayNames(dirs).join(QStringLiteral(", ")).toStdString() << endl; - }); - QObject::connect(this, &SyncthingConnection::newDevices, [](const auto &devs) { - std::cerr << Phrases::Info << "Device list renewed:" << Phrases::End; - std::cerr << displayNames(devs).join(QStringLiteral(", ")).toStdString() << endl; - }); -#endif + setLoggingFlags(loggingFlags); } /*! @@ -172,6 +168,49 @@ QString SyncthingConnection::statusText(SyncthingStatus status) } } +/*! + * \brief Sets the specified logging \a flags. + */ +void SyncthingConnection::setLoggingFlags(SyncthingConnectionLoggingFlags flags) +{ + m_loggingFlags = flags; + if (flags & SyncthingConnectionLoggingFlags::FromEnvironment) { + if (!(flags & SyncthingConnectionLoggingFlags::All) && qEnvironmentVariableIntValue(PROJECT_VARNAME_UPPER "_LOG_ALL")) { + m_loggingFlags |= SyncthingConnectionLoggingFlags::All; + } else { + if (!(flags & SyncthingConnectionLoggingFlags::ApiCalls) && qEnvironmentVariableIntValue(PROJECT_VARNAME_UPPER "_LOG_API_CALLS")) { + m_loggingFlags |= SyncthingConnectionLoggingFlags::ApiCalls; + } + if (!(flags & SyncthingConnectionLoggingFlags::ApiCalls) && qEnvironmentVariableIntValue(PROJECT_VARNAME_UPPER "_LOG_API_REPLIES")) { + m_loggingFlags |= SyncthingConnectionLoggingFlags::ApiCalls; + } + if (!(flags & SyncthingConnectionLoggingFlags::Events) && qEnvironmentVariableIntValue(PROJECT_VARNAME_UPPER "_LOG_EVENTS")) { + m_loggingFlags |= SyncthingConnectionLoggingFlags::Events; + } + if (!(flags & SyncthingConnectionLoggingFlags::DirsOrDevsResetted) + && qEnvironmentVariableIntValue(PROJECT_VARNAME_UPPER "_LOG_DIRS_OR_DEVS_RESETTED")) { + m_loggingFlags |= SyncthingConnectionLoggingFlags::Events; + } + } + } + if ((m_loggingFlags & SyncthingConnectionLoggingFlags::DirsOrDevsResetted) + && !(m_loggingFlagsHandler & SyncthingConnectionLoggingFlags::DirsOrDevsResetted)) { + QObject::connect(this, &SyncthingConnection::newDirs, [this](const auto &dirs) { + if (m_loggingFlags & SyncthingConnectionLoggingFlags::DirsOrDevsResetted) { + std::cerr << Phrases::Info << "Directory list renewed:" << Phrases::End; + std::cerr << displayNames(dirs).join(QStringLiteral(", ")).toStdString() << endl; + } + }); + QObject::connect(this, &SyncthingConnection::newDevices, [this](const auto &devs) { + if (m_loggingFlags & SyncthingConnectionLoggingFlags::DirsOrDevsResetted) { + std::cerr << Phrases::Info << "Device list renewed:" << Phrases::End; + std::cerr << displayNames(devs).join(QStringLiteral(", ")).toStdString() << endl; + } + }); + m_loggingFlagsHandler |= SyncthingConnectionLoggingFlags::DirsOrDevsResetted; + } +} + /*! * \brief Returns whether there is at least one directory out-of-sync. */ diff --git a/connector/syncthingconnection.h b/connector/syncthingconnection.h index 6c6a951..9fc4cd3 100644 --- a/connector/syncthingconnection.h +++ b/connector/syncthingconnection.h @@ -5,6 +5,9 @@ #include "./syncthingdev.h" #include "./syncthingdir.h" +#include + +#include #include #include #include @@ -49,6 +52,22 @@ struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingLogEntry { QString message; }; +enum class SyncthingConnectionLoggingFlags : quint64 { + None, /**< loggingn is disabled */ + FromEnvironment = (1 << 0), /**< environment variables are checked to pull in any of the other flags dynamically */ + ApiCalls = (1 << 1), /**< log calls to Syncthing's REST-API and responses */ + ApiReplies = (1 << 2), /**< log replies fromm Syncthing's REST-API */ + Events = (1 << 3), /**< log events received via Syncthing's event API */ + DirsOrDevsResetted = (1 << 4), /**< log list of directories/devices when list is resetted */ + All = ApiCalls | ApiReplies | Events | DirsOrDevsResetted, /** log as much as possible */ +}; + +} // namespace Data + +CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(Data, Data::SyncthingConnectionLoggingFlags) + +namespace Data { + class LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingConnection : public QObject { friend ConnectionTests; friend MiscTests; @@ -61,6 +80,7 @@ class LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingConnection : public QObject { Q_PROPERTY(QString password READ password) Q_PROPERTY(Data::SyncthingStatus status READ status NOTIFY statusChanged) Q_PROPERTY(Data::SyncthingStatusComputionFlags statusComputionFlags READ statusComputionFlags WRITE setStatusComputionFlags) + Q_PROPERTY(Data::SyncthingConnectionLoggingFlags loggingFlags READ loggingFlags WRITE setLoggingFlags) Q_PROPERTY(QString statusText READ statusText NOTIFY statusChanged) Q_PROPERTY(bool connected READ isConnected NOTIFY statusChanged) Q_PROPERTY(bool hasUnreadNotifications READ hasUnreadNotifications) @@ -87,8 +107,8 @@ class LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingConnection : public QObject { Q_PROPERTY(QJsonObject rawConfig READ rawConfig NOTIFY newConfig) public: - explicit SyncthingConnection( - const QString &syncthingUrl = QStringLiteral("http://localhost:8080"), const QByteArray &apiKey = QByteArray(), QObject *parent = nullptr); + explicit SyncthingConnection(const QString &syncthingUrl = QStringLiteral("http://localhost:8080"), const QByteArray &apiKey = QByteArray(), + SyncthingConnectionLoggingFlags loggingFlags = SyncthingConnectionLoggingFlags::FromEnvironment, QObject *parent = nullptr); ~SyncthingConnection() override; // getter/setter for @@ -107,6 +127,8 @@ public: static QString statusText(SyncthingStatus status); SyncthingStatusComputionFlags statusComputionFlags() const; void setStatusComputionFlags(SyncthingStatusComputionFlags flags); + SyncthingConnectionLoggingFlags loggingFlags() const; + void setLoggingFlags(SyncthingConnectionLoggingFlags flags); bool isConnected() const; bool hasPendingRequests() const; bool hasPendingRequestsIncludingEvents() const; @@ -308,12 +330,17 @@ private Q_SLOTS: private: // internal helper methods + struct Reply { + QNetworkReply *reply; + QByteArray response; + }; QNetworkRequest prepareRequest(const QString &path, const QUrlQuery &query, bool rest = true); QNetworkReply *requestData(const QString &path, const QUrlQuery &query, bool rest = true); QNetworkReply *postData(const QString &path, const QUrlQuery &query, const QByteArray &data = QByteArray()); - QNetworkReply *prepareReply(); - QNetworkReply *prepareReply(QNetworkReply *&expectedReply); - QNetworkReply *prepareReply(QList &expectedReplies); + Reply prepareReply(bool readData = true, bool handleAborting = true); + Reply prepareReply(QNetworkReply *&expectedReply, bool readData = true, bool handleAborting = true); + Reply prepareReply(QList &expectedReplies, bool readData = true, bool handleAborting = true); + Reply handleReply(QNetworkReply *reply, bool readData, bool handleAborting); bool pauseResumeDevice(const QStringList &devIds, bool paused); bool pauseResumeDirectory(const QStringList &dirIds, bool paused); SyncthingDir *addDirInfo(std::vector &dirs, const QString &dirId); @@ -325,6 +352,8 @@ private: QString m_password; SyncthingStatus m_status; SyncthingStatusComputionFlags m_statusComputionFlags; + SyncthingConnectionLoggingFlags m_loggingFlags; + SyncthingConnectionLoggingFlags m_loggingFlagsHandler; bool m_keepPolling; bool m_abortingAllRequests; @@ -650,6 +679,14 @@ inline void SyncthingConnection::setStatusComputionFlags(SyncthingStatusComputio } } +/*! + * \brief Returns the currently active logging flags. + */ +inline SyncthingConnectionLoggingFlags SyncthingConnection::loggingFlags() const +{ + return m_loggingFlags; +} + /*! * \brief Returns the Syncthing home/configuration directory. */ diff --git a/connector/syncthingconnection_requests.cpp b/connector/syncthingconnection_requests.cpp index d6fd6aa..8dc1dce 100644 --- a/connector/syncthingconnection_requests.cpp +++ b/connector/syncthingconnection_requests.cpp @@ -52,9 +52,9 @@ QNetworkReply *SyncthingConnection::requestData(const QString &path, const QUrlQ { #ifndef LIB_SYNCTHING_CONNECTOR_CONNECTION_MOCKED auto *const reply = networkAccessManager().get(prepareRequest(path, query, rest)); -#ifdef LIB_SYNCTHING_CONNECTOR_LOG_API_CALLS - cerr << Phrases::Info << "GETing: " << reply->url().toString().toStdString() << Phrases::EndFlush; -#endif + if (loggingFlags() & SyncthingConnectionLoggingFlags::ApiCalls) { + cerr << Phrases::Info << "Querying API: GET " << reply->url().toString().toStdString() << Phrases::EndFlush; + } reply->ignoreSslErrors(m_expectedSslErrors); return reply; #else @@ -68,9 +68,9 @@ QNetworkReply *SyncthingConnection::requestData(const QString &path, const QUrlQ QNetworkReply *SyncthingConnection::postData(const QString &path, const QUrlQuery &query, const QByteArray &data) { auto *const reply = networkAccessManager().post(prepareRequest(path, query), data); -#ifdef LIB_SYNCTHING_CONNECTOR_LOG_API_CALLS - cerr << Phrases::Info << "POSTing: " << reply->url().toString().toStdString() << Phrases::End << data.data() << endl; -#endif + if (loggingFlags() & SyncthingConnectionLoggingFlags::ApiCalls) { + cerr << Phrases::Info << "Querying API: POST " << reply->url().toString().toStdString() << Phrases::EndFlush; + } reply->ignoreSslErrors(m_expectedSslErrors); return reply; } @@ -78,60 +78,62 @@ QNetworkReply *SyncthingConnection::postData(const QString &path, const QUrlQuer /*! * \brief Prepares the current reply. */ -QNetworkReply *SyncthingConnection::prepareReply() +SyncthingConnection::Reply SyncthingConnection::prepareReply(bool readData, bool handleAborting) { - auto *const reply = static_cast(sender()); - reply->deleteLater(); - - // skip further processing if aborting to reconnect - if (m_abortingToReconnect) { - handleAdditionalRequestCanceled(); - return nullptr; - } - - return reply; + return handleReply(static_cast(sender()), readData, handleAborting); } /*! * \brief Prepares the current reply. */ -QNetworkReply *SyncthingConnection::prepareReply(QNetworkReply *&expectedReply) +SyncthingConnection::Reply SyncthingConnection::prepareReply(QNetworkReply *&expectedReply, bool readData, bool handleAborting) { auto *const reply = static_cast(sender()); - reply->deleteLater(); - - // unset the expected reply so it is no longer considered pending if (reply == expectedReply) { - expectedReply = nullptr; + expectedReply = nullptr; // unset the expected reply so it is no longer considered pending } - - // skip further processing if aborting to reconnect - if (m_abortingToReconnect) { - handleAdditionalRequestCanceled(); - return nullptr; - } - - return reply; + return handleReply(reply, readData, handleAborting); } /*! * \brief Prepares the current reply. */ -QNetworkReply *SyncthingConnection::prepareReply(QList &expectedReplies) +SyncthingConnection::Reply SyncthingConnection::prepareReply(QList &expectedReplies, bool readData, bool handleAborting) { auto *const reply = static_cast(sender()); + expectedReplies.removeAll(reply); // unset the expected reply so it is no longer considered pending + return handleReply(reply, readData, handleAborting); +} + +/*! + * \brief Handles the specified \a reply; invoked by the prepareReply() functions. + */ +SyncthingConnection::Reply SyncthingConnection::handleReply(QNetworkReply *reply, bool readData, bool handleAborting) +{ + const auto log = m_loggingFlags & SyncthingConnectionLoggingFlags::ApiReplies; + readData = readData || log; + handleAborting = handleAborting && m_abortingAllRequests; + const auto data = Reply{ + .reply = handleAborting ? nullptr : reply, // skip further processing if aborting to reconnect + .response = readData ? reply->readAll() : QByteArray(), + }; reply->deleteLater(); - // unset the expected reply so it is no longer considered pending - expectedReplies.removeAll(reply); - - // skip further processing if aborting to reconnect - if (m_abortingToReconnect) { - handleAdditionalRequestCanceled(); - return nullptr; + if (log) { + const auto url = reply->url(); + const auto path = url.path().toUtf8(); + const auto urlStr = url.toString().toUtf8(); + cerr << Phrases::Info << "Received reply for: " << std::string_view(urlStr.data(), static_cast(urlStr.size())) + << Phrases::EndFlush; + if (!data.response.isEmpty() && path != "/rest/events" + && path != "/rest/events/disk") { // events are logged separately because they are not always useful but make the log very verbose + cerr << std::string_view(data.response.data(), static_cast(data.response.size())); + } } - - return reply; + if (handleAborting) { + handleAdditionalRequestCanceled(); + } + return data; } // pause/resume devices @@ -212,14 +214,14 @@ bool SyncthingConnection::pauseResumeDevice(const QStringList &devIds, bool paus */ void SyncthingConnection::readDevPauseResume() { - auto *const reply = prepareReply(); + auto const [reply, response] = prepareReply(false); if (!reply) { return; } switch (reply->error()) { case QNetworkReply::NoError: { - const QStringList devIds(reply->property("devIds").toStringList()); + const QStringList devIds = reply->property("devIds").toStringList(); const bool resume = reply->property("resume").toBool(); setDevicesPaused(m_rawConfig, devIds, !resume); if (reply->property("resume").toBool()) { @@ -316,14 +318,14 @@ bool SyncthingConnection::pauseResumeDirectory(const QStringList &dirIds, bool p void SyncthingConnection::readDirPauseResume() { - auto *const reply = prepareReply(); + auto const [reply, response] = prepareReply(false); if (!reply) { return; } switch (reply->error()) { case QNetworkReply::NoError: { - const QStringList dirIds(reply->property("dirIds").toStringList()); + const QStringList dirIds = reply->property("dirIds").toStringList(); const bool resume = reply->property("resume").toBool(); setDirectoriesPaused(m_rawConfig, dirIds, !resume); if (resume) { @@ -385,7 +387,7 @@ void SyncthingConnection::rescan(const QString &dirId, const QString &relpath) */ void SyncthingConnection::readRescan() { - auto *const reply = prepareReply(); + auto const [reply, response] = prepareReply(false); if (!reply) { return; } @@ -416,7 +418,7 @@ void SyncthingConnection::restart() */ void SyncthingConnection::readRestart() { - auto *const reply = prepareReply(); + auto const [reply, response] = prepareReply(false); if (!reply) { return; } @@ -445,7 +447,7 @@ void SyncthingConnection::shutdown() */ void SyncthingConnection::readShutdown() { - auto *const reply = prepareReply(); + auto const [reply, response] = prepareReply(false); if (!reply) { return; } @@ -477,7 +479,7 @@ void SyncthingConnection::requestClearingErrors() */ void SyncthingConnection::readClearingErrors() { - auto *const reply = prepareReply(); + auto const [reply, response] = prepareReply(false); if (!reply) { return; } @@ -511,14 +513,13 @@ void SyncthingConnection::requestConfig() */ void SyncthingConnection::readConfig() { - auto *const reply = prepareReply(m_configReply); + auto const [reply, response] = prepareReply(m_configReply); if (!reply) { return; } switch (reply->error()) { case QNetworkReply::NoError: { - const QByteArray response(reply->readAll()); QJsonParseError jsonError; const QJsonDocument replyDoc = QJsonDocument::fromJson(response, &jsonError); if (jsonError.error != QJsonParseError::NoError) { @@ -655,14 +656,13 @@ void SyncthingConnection::requestStatus() */ void SyncthingConnection::readStatus() { - auto *const reply = prepareReply(m_statusReply); + auto const [reply, response] = prepareReply(m_statusReply); if (!reply) { return; } switch (reply->error()) { case QNetworkReply::NoError: { - const QByteArray response(reply->readAll()); QJsonParseError jsonError; const auto replyDoc(QJsonDocument::fromJson(response, &jsonError)); if (jsonError.error != QJsonParseError::NoError) { @@ -728,14 +728,13 @@ void SyncthingConnection::requestConnections() */ void SyncthingConnection::readConnections() { - auto *const reply = prepareReply(m_connectionsReply); + auto const [reply, response] = prepareReply(m_connectionsReply); if (!reply) { return; } switch (reply->error()) { case QNetworkReply::NoError: { - const QByteArray response(reply->readAll()); QJsonParseError jsonError; const QJsonDocument replyDoc = QJsonDocument::fromJson(response, &jsonError); if (jsonError.error != QJsonParseError::NoError) { @@ -837,7 +836,7 @@ void SyncthingConnection::requestErrors() */ void SyncthingConnection::readErrors() { - auto *const reply = prepareReply(m_errorsReply); + auto const [reply, response] = prepareReply(m_errorsReply); if (!reply) { return; } @@ -849,7 +848,6 @@ void SyncthingConnection::readErrors() switch (reply->error()) { case QNetworkReply::NoError: { - const QByteArray response(reply->readAll()); QJsonParseError jsonError; const QJsonDocument replyDoc = QJsonDocument::fromJson(response, &jsonError); if (jsonError.error != QJsonParseError::NoError) { @@ -909,14 +907,13 @@ void SyncthingConnection::requestDirStatistics() */ void SyncthingConnection::readDirStatistics() { - auto *const reply = prepareReply(m_dirStatsReply); + auto const [reply, response] = prepareReply(m_dirStatsReply); if (!reply) { return; } switch (reply->error()) { case QNetworkReply::NoError: { - const QByteArray response(reply->readAll()); QJsonParseError jsonError; const QJsonDocument replyDoc = QJsonDocument::fromJson(response, &jsonError); if (jsonError.error != QJsonParseError::NoError) { @@ -1000,7 +997,7 @@ void SyncthingConnection::requestDirStatus(const QString &dirId) */ void SyncthingConnection::readDirStatus() { - auto *const reply = prepareReply(m_otherReplies); + auto const [reply, response] = prepareReply(m_otherReplies); if (!reply) { return; } @@ -1017,7 +1014,6 @@ void SyncthingConnection::readDirStatus() } // parse JSON - const QByteArray response(reply->readAll()); QJsonParseError jsonError; const QJsonDocument replyDoc = QJsonDocument::fromJson(response, &jsonError); if (jsonError.error != QJsonParseError::NoError) { @@ -1063,7 +1059,7 @@ void SyncthingConnection::requestDirPullErrors(const QString &dirId, int page, i */ void SyncthingConnection::readDirPullErrors() { - auto *const reply = prepareReply(); + auto const [reply, response] = prepareReply(); if (!reply) { return; } @@ -1080,7 +1076,6 @@ void SyncthingConnection::readDirPullErrors() switch (reply->error()) { case QNetworkReply::NoError: { // parse JSON - const QByteArray response(reply->readAll()); QJsonParseError jsonError; const QJsonDocument replyDoc = QJsonDocument::fromJson(response, &jsonError); if (jsonError.error != QJsonParseError::NoError) { @@ -1130,15 +1125,13 @@ static void ensureCompletionNotConsideredRequested(const QString &devId, Syncthi */ void SyncthingConnection::readCompletion() { - auto *reply = prepareReply(m_otherReplies); + auto const [reply, response] = prepareReply(m_otherReplies); const auto cancelled = reply == nullptr; - if (!reply) { - reply = static_cast(sender()); - } + const auto *const sender = cancelled ? static_cast(this->sender()) : reply; // determine relevant dev/dir - const auto devId(reply->property("devId").toString()); - const auto dirId(reply->property("dirId").toString()); + const auto devId = sender->property("devId").toString(); + const auto dirId = sender->property("dirId").toString(); int devIndex, dirIndex; auto *const devInfo = findDevInfo(devId, devIndex); auto *const dirInfo = findDirInfo(dirId, dirIndex); @@ -1154,8 +1147,7 @@ void SyncthingConnection::readCompletion() case QNetworkReply::NoError: { // parse JSON QJsonParseError jsonError; - const auto response(reply->readAll()); - const auto replyDoc(QJsonDocument::fromJson(response, &jsonError)); + const auto replyDoc = QJsonDocument::fromJson(response, &jsonError); if (jsonError.error == QJsonParseError::NoError) { // update the relevant completion info readRemoteFolderCompletion(DateTime::now(), replyDoc.object(), devId, devInfo, devIndex, dirId, dirInfo, dirIndex); @@ -1200,14 +1192,13 @@ void SyncthingConnection::requestDeviceStatistics() */ void SyncthingConnection::readDeviceStatistics() { - auto *const reply = prepareReply(m_devStatsReply); + auto const [reply, response] = prepareReply(m_devStatsReply); if (!reply) { return; } switch (reply->error()) { case QNetworkReply::NoError: { - const QByteArray response(reply->readAll()); QJsonParseError jsonError; const QJsonDocument replyDoc = QJsonDocument::fromJson(response, &jsonError); if (jsonError.error != QJsonParseError::NoError) { @@ -1264,14 +1255,13 @@ void SyncthingConnection::requestVersion() */ void SyncthingConnection::readVersion() { - auto *const reply = prepareReply(m_versionReply); + auto const [reply, response] = prepareReply(m_versionReply); if (!reply) { return; } switch (reply->error()) { case QNetworkReply::NoError: { - const QByteArray response(reply->readAll()); QJsonParseError jsonError; const auto replyDoc(QJsonDocument::fromJson(response, &jsonError)); if (jsonError.error != QJsonParseError::NoError) { @@ -1314,14 +1304,14 @@ void SyncthingConnection::requestQrCode(const QString &text) */ void SyncthingConnection::readQrCode() { - auto *const reply = prepareReply(); + auto const [reply, response] = prepareReply(); if (!reply) { return; } switch (reply->error()) { case QNetworkReply::NoError: - emit qrCodeAvailable(reply->property("qrText").toString(), reply->readAll()); + emit qrCodeAvailable(reply->property("qrText").toString(), response); break; case QNetworkReply::OperationCanceledError: break; @@ -1349,7 +1339,7 @@ void SyncthingConnection::requestLog() */ void SyncthingConnection::readLog() { - auto *const reply = prepareReply(m_logReply); + auto const [reply, response] = prepareReply(m_logReply); if (!reply) { return; } @@ -1357,7 +1347,7 @@ void SyncthingConnection::readLog() switch (reply->error()) { case QNetworkReply::NoError: { QJsonParseError jsonError; - const QJsonDocument replyDoc = QJsonDocument::fromJson(reply->readAll(), &jsonError); + const QJsonDocument replyDoc = QJsonDocument::fromJson(response, &jsonError); if (jsonError.error != QJsonParseError::NoError) { emit error(tr("Unable to parse Syncthing log: ") + jsonError.errorString(), SyncthingErrorCategory::Parsing, QNetworkReply::NoError); return; @@ -1410,8 +1400,7 @@ void SyncthingConnection::postConfigFromByteArray(const QByteArray &rawConfig) */ void SyncthingConnection::readPostConfig() { - auto *const reply = static_cast(sender()); - reply->deleteLater(); + auto const [reply, response] = prepareReply(false, false); switch (reply->error()) { case QNetworkReply::NoError: emit newConfigTriggered(); @@ -1571,14 +1560,13 @@ void SyncthingConnection::requestEvents() */ void SyncthingConnection::readEvents() { - auto *const reply = prepareReply(m_eventsReply); + auto const [reply, response] = prepareReply(m_eventsReply); if (!reply) { return; } switch (reply->error()) { case QNetworkReply::NoError: { - const QByteArray response(reply->readAll()); QJsonParseError jsonError; const QJsonDocument replyDoc = QJsonDocument::fromJson(response, &jsonError); if (jsonError.error != QJsonParseError::NoError) { @@ -1592,12 +1580,10 @@ void SyncthingConnection::readEvents() emit newEvents(replyArray); readEventsFromJsonArray(replyArray, m_lastEventId); -#ifdef LIB_SYNCTHING_CONNECTOR_LOG_SYNCTHING_EVENTS - if (!replyArray.isEmpty()) { - cerr << Phrases::Info << "Received " << replyArray.size() << " Syncthing events:" << Phrases::End - << replyDoc.toJson(QJsonDocument::Indented).data() << endl; + if (!replyArray.isEmpty() && (loggingFlags() & SyncthingConnectionLoggingFlags::Events)) { + const auto log = replyDoc.toJson(QJsonDocument::Indented); + cerr << Phrases::Info << "Received " << replyArray.size() << " Syncthing events:" << Phrases::End << log.data() << endl; } -#endif break; } case QNetworkReply::TimeoutError: @@ -2166,14 +2152,13 @@ void SyncthingConnection::requestDiskEvents(int limit) */ void SyncthingConnection::readDiskEvents() { - auto *const reply = prepareReply(m_diskEventsReply); + auto const [reply, response] = prepareReply(m_diskEventsReply); if (!reply) { return; } switch (reply->error()) { case QNetworkReply::NoError: { - const QByteArray response(reply->readAll()); QJsonParseError jsonError; const auto replyDoc(QJsonDocument::fromJson(response, &jsonError)); if (jsonError.error != QJsonParseError::NoError) { @@ -2181,8 +2166,14 @@ void SyncthingConnection::readDiskEvents() return; } + const auto replyArray = replyDoc.array(); m_hasDiskEvents = true; - readEventsFromJsonArray(replyDoc.array(), m_lastDiskEventId); + readEventsFromJsonArray(replyArray, m_lastDiskEventId); + + if (!replyArray.isEmpty() && (loggingFlags() & SyncthingConnectionLoggingFlags::Events)) { + const auto log = replyDoc.toJson(QJsonDocument::Indented); + cerr << Phrases::Info << "Received " << replyArray.size() << " Syncthing disk events:" << Phrases::End << log.data() << endl; + } break; } case QNetworkReply::TimeoutError: