Refactor monitoring logs handling: use concise JSON formatting for transaction logs, add /monitoring_logs admin endpoint for testing, increase screen monitoring interval to 120s, and simplify network retry logic with shorter monitoring timeouts.
This commit is contained in:
parent
2b4bd5a9d1
commit
c2994d9041
@ -16,7 +16,7 @@ public:
|
||||
|
||||
static constexpr qint64 kOfflineDebounceSecs = 30;
|
||||
// Как часто проверять/слать кадр истории экрана на сервер логов (с дедупом).
|
||||
static constexpr qint64 kMonitoringScreenIntervalSecs = 30;
|
||||
static constexpr qint64 kMonitoringScreenIntervalSecs = 120;
|
||||
// Таймаут одной adb-команды в scanDeviceIo. На порядок выше нормального
|
||||
// времени (<1с), но ограничивает зависшую команду на флапающем устройстве,
|
||||
// чтобы один телефон не держал весь цикл опроса.
|
||||
|
||||
@ -804,7 +804,7 @@ void EventHandler::startThreadForTask(const MaterialInfo &account, const EventIn
|
||||
event.externalId, event.bankName, arr, event.id, /*updateStatus=*/false);
|
||||
// Логируем в arc-monitoring сразу по каждой транзакции — как на apiBase.
|
||||
sendTaskSuccess("FETCH_TRANSACTIONS", event.externalId, event.bankName,
|
||||
QString::fromUtf8(QJsonDocument(tx).toJson(QJsonDocument::Compact)),
|
||||
QStringLiteral("JSON: %1").arg(QString::fromUtf8(QJsonDocument(tx).toJson(QJsonDocument::Indented))),
|
||||
{}, event.id, event.accountId);
|
||||
// Фиксируем в глобальном кэше: будущие задачи того же материала
|
||||
// не будут повторно подтверждать эту транзакцию (TTL 20 минут).
|
||||
|
||||
@ -56,6 +56,9 @@ bool awaitReply(QNetworkReply *reply, int timeoutMs) {
|
||||
constexpr int kMaxRequestAttempts = 3;
|
||||
constexpr int kDefaultTimeoutMs = 30000;
|
||||
constexpr int kDumpTimeoutMs = 120000;
|
||||
// Мониторинг — best-effort: одна попытка, короткий таймаут. Failure не должен
|
||||
// блокировать потоки и накапливать QThread'ы при недоступном сервере.
|
||||
constexpr int kMonitoringTimeoutMs = 10000;
|
||||
} // namespace
|
||||
|
||||
NetworkService::NetworkService(QObject *parent) : QObject(parent) {
|
||||
@ -1655,44 +1658,32 @@ void NetworkService::postMonitoringLog(const QString &type, const QString &event
|
||||
|
||||
const int internalTaskId = m_extraData.value("internal_task_id").toInt();
|
||||
|
||||
QNetworkReply *reply = nullptr;
|
||||
bool timedOut = true;
|
||||
for (int attempt = 1; attempt <= kMaxRequestAttempts; ++attempt) {
|
||||
if (reply) { reply->deleteLater(); reply = nullptr; }
|
||||
|
||||
auto *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
addFormField(multiPart, "type", type.toUpper());
|
||||
addFormField(multiPart, "event", event);
|
||||
addFormField(multiPart, "message", message);
|
||||
if (internalTaskId > 0) {
|
||||
addFormField(multiPart, "internal_task_id", QString::number(internalTaskId));
|
||||
}
|
||||
if (!image.isEmpty()) {
|
||||
QHttpPart imagePart;
|
||||
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");
|
||||
imagePart.setHeader(
|
||||
QNetworkRequest::ContentDispositionHeader,
|
||||
QStringLiteral("form-data; name=\"image\"; filename=\"screenshot.png\"")
|
||||
);
|
||||
imagePart.setBody(image);
|
||||
multiPart->append(imagePart);
|
||||
}
|
||||
|
||||
reply = m_manager->post(request, multiPart);
|
||||
multiPart->setParent(reply);
|
||||
|
||||
if (awaitReply(reply, kDefaultTimeoutMs)) { timedOut = false; break; }
|
||||
qWarning() << "[NetworkService] postMonitoringLog timeout attempt"
|
||||
<< attempt << "/" << kMaxRequestAttempts;
|
||||
reply->abort();
|
||||
auto *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
addFormField(multiPart, "type", type.toUpper());
|
||||
addFormField(multiPart, "event", event);
|
||||
addFormField(multiPart, "message", message);
|
||||
if (internalTaskId > 0) {
|
||||
addFormField(multiPart, "internal_task_id", QString::number(internalTaskId));
|
||||
}
|
||||
if (!image.isEmpty()) {
|
||||
QHttpPart imagePart;
|
||||
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");
|
||||
imagePart.setHeader(
|
||||
QNetworkRequest::ContentDispositionHeader,
|
||||
QStringLiteral("form-data; name=\"image\"; filename=\"screenshot.png\"")
|
||||
);
|
||||
imagePart.setBody(image);
|
||||
multiPart->append(imagePart);
|
||||
}
|
||||
|
||||
if (timedOut) {
|
||||
qWarning() << "[NetworkService] postMonitoringLog timeout after"
|
||||
<< kMaxRequestAttempts << "attempts";
|
||||
QNetworkReply *reply = m_manager->post(request, multiPart);
|
||||
multiPart->setParent(reply);
|
||||
|
||||
if (!awaitReply(reply, kMonitoringTimeoutMs)) {
|
||||
qWarning() << "[NetworkService] postMonitoringLog timeout";
|
||||
reply->abort();
|
||||
} else if (reply->error() != QNetworkReply::NoError) {
|
||||
qWarning() << "[NetworkService] postMonitoringLog failed:" << reply->errorString()
|
||||
<< "\n response body:" << reply->readAll();
|
||||
qWarning() << "[NetworkService] postMonitoringLog failed:" << reply->errorString();
|
||||
}
|
||||
reply->deleteLater();
|
||||
}
|
||||
@ -1778,39 +1769,27 @@ void NetworkService::postMonitoringScreenshot(const QString &desktopId,
|
||||
request.setRawHeader("X-Monitoring-Token", m_monitoringToken.toUtf8());
|
||||
}
|
||||
|
||||
QNetworkReply *reply = nullptr;
|
||||
bool timedOut = true;
|
||||
for (int attempt = 1; attempt <= kMaxRequestAttempts; ++attempt) {
|
||||
if (reply) { reply->deleteLater(); reply = nullptr; }
|
||||
auto *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
addFormField(multiPart, "desktop_id", desktopId);
|
||||
addFormField(multiPart, "device_id", deviceId);
|
||||
addFormField(multiPart, "name", name);
|
||||
QHttpPart imagePart;
|
||||
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/jpeg");
|
||||
imagePart.setHeader(
|
||||
QNetworkRequest::ContentDispositionHeader,
|
||||
QStringLiteral("form-data; name=\"image\"; filename=\"screen.jpg\"")
|
||||
);
|
||||
imagePart.setBody(jpeg);
|
||||
multiPart->append(imagePart);
|
||||
|
||||
auto *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
addFormField(multiPart, "desktop_id", desktopId);
|
||||
addFormField(multiPart, "device_id", deviceId);
|
||||
addFormField(multiPart, "name", name);
|
||||
QHttpPart imagePart;
|
||||
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/jpeg");
|
||||
imagePart.setHeader(
|
||||
QNetworkRequest::ContentDispositionHeader,
|
||||
QStringLiteral("form-data; name=\"image\"; filename=\"screen.jpg\"")
|
||||
);
|
||||
imagePart.setBody(jpeg);
|
||||
multiPart->append(imagePart);
|
||||
QNetworkReply *reply = m_manager->post(request, multiPart);
|
||||
multiPart->setParent(reply);
|
||||
|
||||
reply = m_manager->post(request, multiPart);
|
||||
multiPart->setParent(reply);
|
||||
|
||||
if (awaitReply(reply, kDefaultTimeoutMs)) { timedOut = false; break; }
|
||||
qWarning() << "[NetworkService] postMonitoringScreenshot timeout attempt"
|
||||
<< attempt << "/" << kMaxRequestAttempts;
|
||||
if (!awaitReply(reply, kMonitoringTimeoutMs)) {
|
||||
qWarning() << "[NetworkService] postMonitoringScreenshot timeout";
|
||||
reply->abort();
|
||||
}
|
||||
|
||||
if (timedOut) {
|
||||
qWarning() << "[NetworkService] postMonitoringScreenshot timeout after"
|
||||
<< kMaxRequestAttempts << "attempts";
|
||||
} else if (reply->error() != QNetworkReply::NoError) {
|
||||
qWarning() << "[NetworkService] postMonitoringScreenshot failed:" << reply->errorString()
|
||||
<< "\n response body:" << reply->readAll();
|
||||
qWarning() << "[NetworkService] postMonitoringScreenshot failed:" << reply->errorString();
|
||||
}
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
@ -522,6 +522,17 @@ def monitoring_log():
|
||||
return ok({})
|
||||
|
||||
|
||||
@app.get("/_admin/monitoring_logs")
|
||||
def admin_monitoring_logs():
|
||||
"""Return collected monitoring logs for testing."""
|
||||
event_filter = request.args.get("event")
|
||||
with _lock:
|
||||
logs = list(_monitoring_logs)
|
||||
if event_filter:
|
||||
logs = [l for l in logs if l["event"] == event_filter]
|
||||
return jsonify(logs)
|
||||
|
||||
|
||||
@app.get("/_admin/screenshot/<image_id>")
|
||||
def get_screenshot(image_id):
|
||||
path = _SCREENSHOTS_DIR / f"{image_id}.png"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user