Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/client status reporting #6247

Merged
merged 9 commits into from
Dec 11, 2023
Prev Previous commit
Next Next commit
Allow sending E2EE and Virus_Detected statuses. Also updated tests.
Signed-off-by: alex-z <[email protected]>
  • Loading branch information
allexzander committed Dec 11, 2023
commit 1828c4f73a59ccfe9e435074d5eb1c3a57e28c4e
2 changes: 1 addition & 1 deletion src/gui/tray/NCBusyIndicator.qml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ BusyIndicator {

RotationAnimator {
target: contentImage
running: root.running
running: false
onRunningChanged: contentImage.rotation = 0
from: 0
to: 360
Expand Down
73 changes: 49 additions & 24 deletions src/libsync/clientstatusreporting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ namespace
{
constexpr auto lastSentReportTimestamp = "lastClientStatusReportSentTime";
constexpr auto statusNamesHash = "statusNamesHash";

constexpr auto statusReportCategoryE2eErrors = "e2e_errors";
constexpr auto statusReportCategoryProblems = "problems";
constexpr auto statusReportCategorySyncConflicts = "sync_conflicts";
constexpr auto statusReportCategoryVirus = "virus_detected";
}

namespace OCC
Expand Down Expand Up @@ -300,13 +305,15 @@ QVariantMap ClientStatusReporting::prepareReport() const
}

QVariantMap report;
report[QStringLiteral("sync_conflicts")] = QVariantMap{};
report[QStringLiteral("problems")] = QVariantMap{};
report[QStringLiteral("virus_detected")] = QVariantMap{};
report[QStringLiteral("e2e_errors")] = QVariantMap{};
report[statusReportCategorySyncConflicts] = QVariantMap{};
report[statusReportCategoryProblems] = QVariantMap{};
report[statusReportCategoryVirus] = QVariantMap{};
report[statusReportCategoryE2eErrors] = QVariantMap{};

QVariantMap syncConflicts;
QVariantMap e2eeErrors;
QVariantMap problems;
QVariantMap syncConflicts;
QVariantMap virusDetectedErrors;

for (const auto &record : records) {
const auto categoryKey = classifyStatus(static_cast<Status>(record._status));
Expand All @@ -315,15 +322,25 @@ QVariantMap ClientStatusReporting::prepareReport() const
qCDebug(lcClientStatusReporting) << "Could not classify status:";
continue;
}

if (categoryKey == QStringLiteral("sync_conflicts")) {

if (categoryKey == statusReportCategoryE2eErrors) {
const auto initialCount = e2eeErrors[QStringLiteral("count")].toInt();
e2eeErrors[QStringLiteral("count")] = initialCount + record._numOccurences;
e2eeErrors[QStringLiteral("oldest")] = record._lastOccurence;
report[categoryKey] = e2eeErrors;
} else if (categoryKey == statusReportCategoryProblems) {
problems[record._name] = QVariantMap{{QStringLiteral("count"), record._numOccurences}, {QStringLiteral("oldest"), record._lastOccurence}};
report[categoryKey] = problems;
} else if (categoryKey == statusReportCategorySyncConflicts) {
const auto initialCount = syncConflicts[QStringLiteral("count")].toInt();
syncConflicts[QStringLiteral("count")] = initialCount + record._numOccurences;
syncConflicts[QStringLiteral("oldest")] = record._lastOccurence;
report[categoryKey] = syncConflicts;
} else if (categoryKey == QStringLiteral("problems")) {
problems[record._name] = QVariantMap{{QStringLiteral("count"), record._numOccurences}, {QStringLiteral("oldest"), record._lastOccurence}};
report[categoryKey] = problems;
} else if (categoryKey == statusReportCategoryVirus) {
const auto initialCount = virusDetectedErrors[QStringLiteral("count")].toInt();
virusDetectedErrors[QStringLiteral("count")] = initialCount + record._numOccurences;
virusDetectedErrors[QStringLiteral("oldest")] = record._lastOccurence;
report[categoryKey] = virusDetectedErrors;
}
}
return report;
Expand Down Expand Up @@ -352,29 +369,33 @@ QByteArray ClientStatusReporting::statusStringFromNumber(const Status status)

switch (status) {
case DownloadError_Cannot_Create_File:
return QByteArrayLiteral("DownloadError.CANNOT_CREATE_FILE");
return QByteArrayLiteral("DownloadResult.CANNOT_CREATE_FILE");
case DownloadError_Conflict:
return QByteArrayLiteral("DownloadError.CONFLICT");
return QByteArrayLiteral("DownloadResult.CONFLICT");
case DownloadError_ConflictCaseClash:
return QByteArrayLiteral("DownloadError.CONFLICT_CASECLASH");
return QByteArrayLiteral("DownloadResult.CONFLICT_CASECLASH");
case DownloadError_ConflictInvalidCharacters:
return QByteArrayLiteral("DownloadError.CONFLICT_INVALID_CHARACTERS");
return QByteArrayLiteral("DownloadResult.CONFLICT_INVALID_CHARACTERS");
case DownloadError_No_Free_Space:
return QByteArrayLiteral("DownloadError.NO_FREE_SPACE");
return QByteArrayLiteral("DownloadResult.NO_FREE_SPACE");
case DownloadError_ServerError:
return QByteArrayLiteral("DownloadError.SERVER_ERROR");
return QByteArrayLiteral("DownloadResult.SERVER_ERROR");
case DownloadError_Virtual_File_Hydration_Failure:
return QByteArrayLiteral("DownloadError.VIRTUAL_FILE_HYDRATION_FAILURE ");
return QByteArrayLiteral("DownloadResult.VIRTUAL_FILE_HYDRATION_FAILURE");
case E2EeError_GeneralError:
return QByteArrayLiteral("E2EeError.General");
case UploadError_Conflict:
return QByteArrayLiteral("UploadError.CONFLICT_CASECLASH");
return QByteArrayLiteral("UploadResult.CONFLICT_CASECLASH");
case UploadError_ConflictInvalidCharacters:
return QByteArrayLiteral("UploadError.CONFLICT_INVALID_CHARACTERS");
return QByteArrayLiteral("UploadResult.CONFLICT_INVALID_CHARACTERS");
case UploadError_No_Free_Space:
return QByteArrayLiteral("UploadError.NO_FREE_SPACE");
return QByteArrayLiteral("UploadResult.NO_FREE_SPACE");
case UploadError_No_Write_Permissions:
return QByteArrayLiteral("UploadError.NO_WRITE_PERMISSIONS");
return QByteArrayLiteral("UploadResult.NO_WRITE_PERMISSIONS");
case UploadError_ServerError:
return QByteArrayLiteral("UploadError.SERVER_ERROR");
return QByteArrayLiteral("UploadResult.SERVER_ERROR");
case UploadError_Virus_Detected:
return QByteArrayLiteral("UploadResult.VIRUS_DETECTED");
case Count:
return {};
};
Expand All @@ -395,15 +416,19 @@ QByteArray ClientStatusReporting::classifyStatus(const Status status)
case DownloadError_ConflictInvalidCharacters:
case UploadError_Conflict:
case UploadError_ConflictInvalidCharacters:
return QByteArrayLiteral("sync_conflicts");
return statusReportCategorySyncConflicts;
case DownloadError_Cannot_Create_File:
case DownloadError_No_Free_Space:
case DownloadError_ServerError:
case DownloadError_Virtual_File_Hydration_Failure:
case UploadError_No_Free_Space:
case UploadError_No_Write_Permissions:
case UploadError_ServerError:
return QByteArrayLiteral("problems");
return statusReportCategoryProblems;
case UploadError_Virus_Detected:
return statusReportCategoryVirus;
case E2EeError_GeneralError:
return statusReportCategoryE2eErrors;
case Count:
return {};
};
Expand Down
2 changes: 2 additions & 0 deletions src/libsync/clientstatusreporting.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ class OWNCLOUDSYNC_EXPORT ClientStatusReporting : public QObject
DownloadError_No_Free_Space,
DownloadError_ServerError,
DownloadError_Virtual_File_Hydration_Failure,
E2EeError_GeneralError,
UploadError_Conflict,
UploadError_ConflictInvalidCharacters,
UploadError_No_Free_Space,
UploadError_No_Write_Permissions,
UploadError_ServerError,
UploadError_Virus_Detected,
Count,
};

Expand Down
21 changes: 18 additions & 3 deletions test/testclientstatusreporting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,28 @@ private slots:
account->reportClientStatus(OCC::ClientStatusReporting::Status::UploadError_No_Write_Permissions);
account->reportClientStatus(OCC::ClientStatusReporting::Status::UploadError_No_Write_Permissions);
account->reportClientStatus(OCC::ClientStatusReporting::Status::UploadError_No_Write_Permissions);

// 3 occurances of UploadError_Virus_Detected
account->reportClientStatus(OCC::ClientStatusReporting::Status::UploadError_Virus_Detected);
account->reportClientStatus(OCC::ClientStatusReporting::Status::UploadError_Virus_Detected);
account->reportClientStatus(OCC::ClientStatusReporting::Status::UploadError_Virus_Detected);

// 2 occurances of E2EeError_GeneralError
account->reportClientStatus(OCC::ClientStatusReporting::Status::E2EeError_GeneralError);
account->reportClientStatus(OCC::ClientStatusReporting::Status::E2EeError_GeneralError);
QTest::qWait(OCC::ClientStatusReporting::clientStatusReportingTrySendTimerInterval + OCC::ClientStatusReporting::repordSendIntervalMs);

QVERIFY(!bodyReceivedAndParsed.isEmpty());

// we must have "virus_detected" and "e2e_errors" keys present (as required by server)
QVERIFY(bodyReceivedAndParsed.contains("virus_detected"));
QVERIFY(bodyReceivedAndParsed.contains("e2e_errors"));
// we must have 2 e2ee errors
const auto virusDetectedErrorsReceived = bodyReceivedAndParsed.value("virus_detected").toMap();
QVERIFY(!virusDetectedErrorsReceived.isEmpty());
QVERIFY(virusDetectedErrorsReceived.size(), 3);

// we must have 2 e2ee errors
const auto e2eeErrorsReceived = bodyReceivedAndParsed.value("e2e_errors").toMap();
QVERIFY(!e2eeErrorsReceived.isEmpty());
QVERIFY(e2eeErrorsReceived.size(), 2);

// we must have 5 conflicts
const auto conflictsReceived = bodyReceivedAndParsed.value("sync_conflicts").toMap();
Expand Down