feat(diagnostics): add "Copy diagnostics" + "Open log folder" actions (Foundation QoL)
Settings (logging section) gains two support-friendly actions, now that the logging foundation actually produces logs (W7-2): - Open log folder: opens the config dir (Platform::openFolder) so users can find dragonx-debug.log / dragonx-crash.log. - Copy diagnostics: copies a plaintext support snapshot to the clipboard via the new App::buildDiagnosticsReport() — version, build variant, platform, connection status, active wallet path + existence + size, encryption/lock state, sync heights, and (full- node) daemon status/running/crash-count/lastError, plus the log paths. No secrets. Build-clean; ctest 1/1. Remaining QoL: persistent alert history, a daemon/RPC error banner, and the W6-2 refresh-staleness badge. See docs/wallet-hardening.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
57
src/app.cpp
57
src/app.cpp
@@ -105,6 +105,7 @@
|
||||
#include <unordered_set>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <exception>
|
||||
@@ -5658,6 +5659,62 @@ void App::maybeFinishTransactionSendProgress()
|
||||
if (addresses_dirty_ || network_refresh_.jobInProgress(Job::Addresses)) return;
|
||||
send_progress_active_ = false;
|
||||
}
|
||||
std::string App::buildDiagnosticsReport()
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "=== ObsidianDragon diagnostics ===\n";
|
||||
os << "version: " << DRAGONX_VERSION << "\n";
|
||||
#if DRAGONX_LITE_BUILD
|
||||
os << "variant: Lite\n";
|
||||
#else
|
||||
os << "variant: Full-node\n";
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
os << "platform: windows\n";
|
||||
#elif defined(__APPLE__)
|
||||
os << "platform: macos\n";
|
||||
#else
|
||||
os << "platform: linux\n";
|
||||
#endif
|
||||
os << "connected: " << (state_.connected ? "yes" : "no") << "\n";
|
||||
os << "status: " << connection_status_ << "\n";
|
||||
|
||||
const std::string activeWallet = settings_ ? settings_->getActiveWalletFile() : std::string("(none)");
|
||||
os << "active wallet: " << activeWallet << "\n";
|
||||
{
|
||||
std::error_code ec;
|
||||
const std::string wp = util::Platform::getDragonXDataDir() + "/" + activeWallet;
|
||||
const bool present = std::filesystem::exists(wp, ec);
|
||||
os << " path: " << wp << (present ? " [present" : " [MISSING");
|
||||
if (present) { auto sz = std::filesystem::file_size(wp, ec); if (!ec) os << ", " << sz << " bytes"; }
|
||||
os << "]\n";
|
||||
}
|
||||
os << "encryption: "
|
||||
<< (state_.encryption_state_known
|
||||
? (state_.encrypted ? (state_.locked ? "encrypted, locked" : "encrypted, unlocked") : "unencrypted")
|
||||
: "unknown")
|
||||
<< "\n";
|
||||
os << "sync: block " << state_.sync.blocks << " / " << state_.sync.headers
|
||||
<< (state_.sync.syncing ? " (syncing)" : "")
|
||||
<< (state_.warming_up ? " (warming up)" : "") << "\n";
|
||||
|
||||
#if !DRAGONX_LITE_BUILD
|
||||
os << "daemon status: " << daemon_status_ << "\n";
|
||||
if (daemon_controller_) {
|
||||
os << "daemon running: " << (daemon_controller_->isRunning() ? "yes" : "no")
|
||||
<< ", crashes: " << daemon_controller_->crashCount() << "\n";
|
||||
const std::string derr = daemon_controller_->lastError();
|
||||
if (!derr.empty()) os << "daemon lastError: " << derr << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
const std::string cfg = util::Platform::getObsidianDragonDir();
|
||||
os << "log folder: " << cfg << "\n";
|
||||
os << " " << cfg << "/dragonx-debug.log\n";
|
||||
os << " " << cfg << "/dragonx-crash.log\n";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void App::restartDaemon()
|
||||
{
|
||||
if (!supportsFullNodeLifecycleActions()) {
|
||||
|
||||
Reference in New Issue
Block a user