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 kOfflineDebounceSecs = 30;
|
||||||
// Как часто проверять/слать кадр истории экрана на сервер логов (с дедупом).
|
// Как часто проверять/слать кадр истории экрана на сервер логов (с дедупом).
|
||||||
static constexpr qint64 kMonitoringScreenIntervalSecs = 30;
|
static constexpr qint64 kMonitoringScreenIntervalSecs = 120;
|
||||||
// Таймаут одной adb-команды в scanDeviceIo. На порядок выше нормального
|
// Таймаут одной adb-команды в scanDeviceIo. На порядок выше нормального
|
||||||
// времени (<1с), но ограничивает зависшую команду на флапающем устройстве,
|
// времени (<1с), но ограничивает зависшую команду на флапающем устройстве,
|
||||||
// чтобы один телефон не держал весь цикл опроса.
|
// чтобы один телефон не держал весь цикл опроса.
|
||||||
|
|||||||
@ -804,7 +804,7 @@ void EventHandler::startThreadForTask(const MaterialInfo &account, const EventIn
|
|||||||
event.externalId, event.bankName, arr, event.id, /*updateStatus=*/false);
|
event.externalId, event.bankName, arr, event.id, /*updateStatus=*/false);
|
||||||
// Логируем в arc-monitoring сразу по каждой транзакции — как на apiBase.
|
// Логируем в arc-monitoring сразу по каждой транзакции — как на apiBase.
|
||||||
sendTaskSuccess("FETCH_TRANSACTIONS", event.externalId, event.bankName,
|
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);
|
{}, event.id, event.accountId);
|
||||||
// Фиксируем в глобальном кэше: будущие задачи того же материала
|
// Фиксируем в глобальном кэше: будущие задачи того же материала
|
||||||
// не будут повторно подтверждать эту транзакцию (TTL 20 минут).
|
// не будут повторно подтверждать эту транзакцию (TTL 20 минут).
|
||||||
|
|||||||
@ -56,6 +56,9 @@ bool awaitReply(QNetworkReply *reply, int timeoutMs) {
|
|||||||
constexpr int kMaxRequestAttempts = 3;
|
constexpr int kMaxRequestAttempts = 3;
|
||||||
constexpr int kDefaultTimeoutMs = 30000;
|
constexpr int kDefaultTimeoutMs = 30000;
|
||||||
constexpr int kDumpTimeoutMs = 120000;
|
constexpr int kDumpTimeoutMs = 120000;
|
||||||
|
// Мониторинг — best-effort: одна попытка, короткий таймаут. Failure не должен
|
||||||
|
// блокировать потоки и накапливать QThread'ы при недоступном сервере.
|
||||||
|
constexpr int kMonitoringTimeoutMs = 10000;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
NetworkService::NetworkService(QObject *parent) : QObject(parent) {
|
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();
|
const int internalTaskId = m_extraData.value("internal_task_id").toInt();
|
||||||
|
|
||||||
QNetworkReply *reply = nullptr;
|
auto *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||||
bool timedOut = true;
|
addFormField(multiPart, "type", type.toUpper());
|
||||||
for (int attempt = 1; attempt <= kMaxRequestAttempts; ++attempt) {
|
addFormField(multiPart, "event", event);
|
||||||
if (reply) { reply->deleteLater(); reply = nullptr; }
|
addFormField(multiPart, "message", message);
|
||||||
|
if (internalTaskId > 0) {
|
||||||
auto *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
addFormField(multiPart, "internal_task_id", QString::number(internalTaskId));
|
||||||
addFormField(multiPart, "type", type.toUpper());
|
}
|
||||||
addFormField(multiPart, "event", event);
|
if (!image.isEmpty()) {
|
||||||
addFormField(multiPart, "message", message);
|
QHttpPart imagePart;
|
||||||
if (internalTaskId > 0) {
|
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");
|
||||||
addFormField(multiPart, "internal_task_id", QString::number(internalTaskId));
|
imagePart.setHeader(
|
||||||
}
|
QNetworkRequest::ContentDispositionHeader,
|
||||||
if (!image.isEmpty()) {
|
QStringLiteral("form-data; name=\"image\"; filename=\"screenshot.png\"")
|
||||||
QHttpPart imagePart;
|
);
|
||||||
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png");
|
imagePart.setBody(image);
|
||||||
imagePart.setHeader(
|
multiPart->append(imagePart);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timedOut) {
|
QNetworkReply *reply = m_manager->post(request, multiPart);
|
||||||
qWarning() << "[NetworkService] postMonitoringLog timeout after"
|
multiPart->setParent(reply);
|
||||||
<< kMaxRequestAttempts << "attempts";
|
|
||||||
|
if (!awaitReply(reply, kMonitoringTimeoutMs)) {
|
||||||
|
qWarning() << "[NetworkService] postMonitoringLog timeout";
|
||||||
|
reply->abort();
|
||||||
} else if (reply->error() != QNetworkReply::NoError) {
|
} else if (reply->error() != QNetworkReply::NoError) {
|
||||||
qWarning() << "[NetworkService] postMonitoringLog failed:" << reply->errorString()
|
qWarning() << "[NetworkService] postMonitoringLog failed:" << reply->errorString();
|
||||||
<< "\n response body:" << reply->readAll();
|
|
||||||
}
|
}
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
@ -1778,39 +1769,27 @@ void NetworkService::postMonitoringScreenshot(const QString &desktopId,
|
|||||||
request.setRawHeader("X-Monitoring-Token", m_monitoringToken.toUtf8());
|
request.setRawHeader("X-Monitoring-Token", m_monitoringToken.toUtf8());
|
||||||
}
|
}
|
||||||
|
|
||||||
QNetworkReply *reply = nullptr;
|
auto *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||||
bool timedOut = true;
|
addFormField(multiPart, "desktop_id", desktopId);
|
||||||
for (int attempt = 1; attempt <= kMaxRequestAttempts; ++attempt) {
|
addFormField(multiPart, "device_id", deviceId);
|
||||||
if (reply) { reply->deleteLater(); reply = nullptr; }
|
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);
|
QNetworkReply *reply = m_manager->post(request, multiPart);
|
||||||
addFormField(multiPart, "desktop_id", desktopId);
|
multiPart->setParent(reply);
|
||||||
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);
|
|
||||||
|
|
||||||
reply = m_manager->post(request, multiPart);
|
if (!awaitReply(reply, kMonitoringTimeoutMs)) {
|
||||||
multiPart->setParent(reply);
|
qWarning() << "[NetworkService] postMonitoringScreenshot timeout";
|
||||||
|
|
||||||
if (awaitReply(reply, kDefaultTimeoutMs)) { timedOut = false; break; }
|
|
||||||
qWarning() << "[NetworkService] postMonitoringScreenshot timeout attempt"
|
|
||||||
<< attempt << "/" << kMaxRequestAttempts;
|
|
||||||
reply->abort();
|
reply->abort();
|
||||||
}
|
|
||||||
|
|
||||||
if (timedOut) {
|
|
||||||
qWarning() << "[NetworkService] postMonitoringScreenshot timeout after"
|
|
||||||
<< kMaxRequestAttempts << "attempts";
|
|
||||||
} else if (reply->error() != QNetworkReply::NoError) {
|
} else if (reply->error() != QNetworkReply::NoError) {
|
||||||
qWarning() << "[NetworkService] postMonitoringScreenshot failed:" << reply->errorString()
|
qWarning() << "[NetworkService] postMonitoringScreenshot failed:" << reply->errorString();
|
||||||
<< "\n response body:" << reply->readAll();
|
|
||||||
}
|
}
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -522,6 +522,17 @@ def monitoring_log():
|
|||||||
return ok({})
|
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>")
|
@app.get("/_admin/screenshot/<image_id>")
|
||||||
def get_screenshot(image_id):
|
def get_screenshot(image_id):
|
||||||
path = _SCREENSHOTS_DIR / f"{image_id}.png"
|
path = _SCREENSHOTS_DIR / f"{image_id}.png"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user