Refactor LogArchiveSender to add collectInto for file bundling; update TaskDumpRecorder to unify archive creation for tasks and logs.
This commit is contained in:
parent
c5f0c035fe
commit
f6d895ab34
@ -270,16 +270,11 @@ void TaskDumpRecorder::finishInternal(const QString &errorMessage) {
|
||||
const QString archivePath = m_folder + ".zip";
|
||||
const QString text = buildCaption(errorMessage);
|
||||
|
||||
// Тот же идентификатор профиля/материала/телефона добавляем в caption архива
|
||||
// логов ([LOGS]), чтобы по общему api-токену можно было разделить операторов.
|
||||
QStringList logsIdLines;
|
||||
if (!m_meta.bankProfileId.isEmpty())
|
||||
logsIdLines << QStringLiteral("Profile: %1").arg(m_meta.bankProfileId.toHtmlEscaped());
|
||||
if (!m_meta.materialId.isEmpty())
|
||||
logsIdLines << QStringLiteral("Material: %1").arg(m_meta.materialId.toHtmlEscaped());
|
||||
if (!m_meta.profilePhone.isEmpty())
|
||||
logsIdLines << QStringLiteral("Phone: %1").arg(m_meta.profilePhone.toHtmlEscaped());
|
||||
const QString logsIdentity = logsIdLines.join(QStringLiteral("\n"));
|
||||
// Имя файла архива на relay: <bank>_<task>_<timestamp>.zip — чтобы дамп
|
||||
// сразу читался по банку и типу задачи без открытия caption'а.
|
||||
const QString stamp = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss");
|
||||
const QString archiveFilename =
|
||||
QStringLiteral("%1_%2_%3.zip").arg(m_bank, m_taskKind, stamp);
|
||||
|
||||
// Финальный скриншот шлём отдельным полем `image`, поэтому сразу читаем
|
||||
// его в память, пока папка ещё цела.
|
||||
@ -291,7 +286,12 @@ void TaskDumpRecorder::finishInternal(const QString &errorMessage) {
|
||||
}
|
||||
}
|
||||
|
||||
QThread *bg = QThread::create([folder, archivePath, text, finalScreenshot, logsIdentity]() {
|
||||
QThread *bg = QThread::create([folder, archivePath, text, finalScreenshot, archiveFilename]() {
|
||||
// Кладём application.log + БД (+WAL/SHM) прямо в папку задачи (подкаталог
|
||||
// logs/), чтобы скрины задачи и логи ушли одним общим архивом, а не двумя
|
||||
// отдельными сообщениями на relay.
|
||||
LogArchiveSender::collectInto(folder + "/logs");
|
||||
|
||||
QByteArray archiveBytes;
|
||||
if (zipFolder(folder, archivePath)) {
|
||||
archiveBytes = readFileBytes(archivePath);
|
||||
@ -314,7 +314,8 @@ void TaskDumpRecorder::finishInternal(const QString &errorMessage) {
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(QString, text),
|
||||
Q_ARG(QByteArray, archiveBytes),
|
||||
Q_ARG(QByteArray, finalScreenshot));
|
||||
Q_ARG(QByteArray, finalScreenshot),
|
||||
Q_ARG(QString, archiveFilename));
|
||||
if (!dispatched) {
|
||||
qCritical() << "[TaskDumpRecorder] invokeMethod(postMonitoringDump) FAILED — "
|
||||
"slot not found or wrong signature for" << folder;
|
||||
@ -323,11 +324,6 @@ void TaskDumpRecorder::finishInternal(const QString &errorMessage) {
|
||||
qWarning() << "[TaskDumpRecorder] no NetworkService — dump dropped for" << folder
|
||||
<< "(setNetworkService was not called at app startup?)";
|
||||
}
|
||||
|
||||
// Следом — application.log + БД (+ WAL/SHM) отдельным архивом.
|
||||
// Запускаем уже ПОСЛЕ того, как task-дамп поставлен в очередь
|
||||
// отправки, чтобы порядок прихода на relay был "дамп → логи".
|
||||
LogArchiveSender::dispatch(QStringLiteral("TASK_ERROR"), -1, logsIdentity);
|
||||
});
|
||||
QObject::connect(bg, &QThread::finished, bg, &QObject::deleteLater);
|
||||
bg->start();
|
||||
|
||||
@ -30,31 +30,11 @@ QString resolveDbPath() {
|
||||
|
||||
// Запускается в worker-потоке. Возвращает байты zip или пустой массив.
|
||||
QByteArray buildArchive() {
|
||||
const QString logPath = QCoreApplication::applicationDirPath() + "/application.log";
|
||||
const QString dbPath = resolveDbPath();
|
||||
|
||||
const bool hasLog = QFile::exists(logPath);
|
||||
const bool hasDb = !dbPath.isEmpty() && QFile::exists(dbPath);
|
||||
if (!hasLog && !hasDb) {
|
||||
qWarning() << "[LogArchiveSender] neither log nor db exists — nothing to archive";
|
||||
return {};
|
||||
}
|
||||
|
||||
const QString tmpDir = QDir::tempPath() + QStringLiteral("/arc_logs_auto_") +
|
||||
QString::number(QDateTime::currentMSecsSinceEpoch());
|
||||
QDir().mkpath(tmpDir);
|
||||
|
||||
if (hasLog) {
|
||||
QFile::copy(logPath, tmpDir + "/application.log");
|
||||
}
|
||||
if (hasDb) {
|
||||
const QString dbBaseName = QFileInfo(dbPath).fileName();
|
||||
QFile::copy(dbPath, tmpDir + "/" + dbBaseName);
|
||||
for (const QString &suffix : {QStringLiteral("-wal"), QStringLiteral("-shm")}) {
|
||||
const QString sidecar = dbPath + suffix;
|
||||
if (QFile::exists(sidecar))
|
||||
QFile::copy(sidecar, tmpDir + "/" + dbBaseName + suffix);
|
||||
}
|
||||
if (!LogArchiveSender::collectInto(tmpDir)) {
|
||||
QDir(tmpDir).removeRecursively();
|
||||
return {};
|
||||
}
|
||||
|
||||
const QString archivePath = tmpDir + ".zip";
|
||||
@ -90,6 +70,34 @@ QByteArray buildArchive() {
|
||||
|
||||
} // namespace
|
||||
|
||||
bool LogArchiveSender::collectInto(const QString &destDir) {
|
||||
const QString logPath = QCoreApplication::applicationDirPath() + "/application.log";
|
||||
const QString dbPath = resolveDbPath();
|
||||
|
||||
const bool hasLog = QFile::exists(logPath);
|
||||
const bool hasDb = !dbPath.isEmpty() && QFile::exists(dbPath);
|
||||
if (!hasLog && !hasDb) {
|
||||
qWarning() << "[LogArchiveSender] neither log nor db exists — nothing to collect";
|
||||
return false;
|
||||
}
|
||||
|
||||
QDir().mkpath(destDir);
|
||||
bool any = false;
|
||||
if (hasLog) {
|
||||
if (QFile::copy(logPath, destDir + "/application.log")) any = true;
|
||||
}
|
||||
if (hasDb) {
|
||||
const QString dbBaseName = QFileInfo(dbPath).fileName();
|
||||
if (QFile::copy(dbPath, destDir + "/" + dbBaseName)) any = true;
|
||||
for (const QString &suffix : {QStringLiteral("-wal"), QStringLiteral("-shm")}) {
|
||||
const QString sidecar = dbPath + suffix;
|
||||
if (QFile::exists(sidecar))
|
||||
QFile::copy(sidecar, destDir + "/" + dbBaseName + suffix);
|
||||
}
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
bool LogArchiveSender::dispatch(const QString &label, int eventId, const QString &extraCaptionHtml) {
|
||||
const QString apiToken = SettingsDAO::get("api_key");
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
|
||||
@ -16,4 +16,10 @@ namespace LogArchiveSender {
|
||||
// Возвращает true если задача поставлена в очередь; реальный результат отправки
|
||||
// не отслеживается (fire-and-forget, как у sendMonitoringLog).
|
||||
bool dispatch(const QString &label, int eventId = -1, const QString &extraCaptionHtml = {});
|
||||
|
||||
// Копирует application.log + БД (+WAL/SHM) в destDir (создаёт каталог при
|
||||
// необходимости). Возвращает true, если скопирован хотя бы один файл.
|
||||
// Используется TaskDumpRecorder, чтобы вложить логи прямо в архив дампа
|
||||
// задачи и слать всё одним файлом, а не двумя отдельными архивами.
|
||||
bool collectInto(const QString &destDir);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user