You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Data-capture audit + tracking epic. A review of the dashboard's persistence layer found we historize only a fraction of the telemetry we fetch — the rest is rendered live and thrown away. This epic tracks persisting the valuable, low-cost series we currently discard, so operators get trends (not just last-value) and history survives restarts/disconnects.
What's persisted today
Only three things become history in SQLite (build/dashboard/mining_dashboard/service/storage_service.py → _create_tables):
Cumulative counters (shares, blocks, proxy results) → store deltas/events, and detect a counter reset (proxy/p2pool restart → counter goes backwards) as a segment break, not a negative rate. Reuse the _shares_to_record pattern (data_service.py:176).
Throttle high-cardinality / slow-moving series (per-worker ~5 min, network hourly) rather than the 30 s loop rate.
Expose new series via /api/state; the actual charts/badges are tracked in the consuming feature issues (below).
Captures
Tier 1 — high value, negligible/low cost
P2Pool block-found events — blocks_found / last_block_found (height) / last_block_ts (collector/pools.py:74). Detect the totalBlocksFound increment (mirror _shares_to_record) → blocks(ts REAL PK, height INT, effort REAL). Blocks are the actual payout events; enables a found-blocks timeline + effort-per-block. ~rows per week. → feeds Flag outages / significant hashrate-loss events on the chart (+ feed Telegram/Healthchecks alerts) #99.
XvB credited history (avg_1h / avg_24h / fail_count / donation_fraction) — currently last-value only in kv_store (storage_service.py:290). Append xvb_history(ts, avg_1h, avg_24h, fail_count, donation_fraction) on each external sync (~5 min, data_service.py:497). The donation controller steers off these — a credited-vs-routed history shows credit-factor & tier-holding over time.
Network series (difficulty / height / reward + pool hashrate) — collector/pools.pyget_network_stats / get_p2pool_stats. Hourly network_history(...). Slow-moving → cheap at hourly; lets earnings estimates be back-tested against real difficulty.
Explicitly NOT captured as a series (would bloat / low value)
CPU% / RAM% / load average (collector/system.py) — high-frequency, low long-term value; keep as live gauges (hourly aggregates only if ever needed).
HugePages used/free — effectively static after boot; live gauge only.
Raw stratum passthrough JSON (get_stratum_stats) — large, redundant with the structured fields.
The full latest_data snapshot — correctly stays a single overwritten last-value blob.
These captures back v1.1 trend/charting features (#116, #99, #104), and the v1.0 dashboard-accuracy issues (#169/#182) don't require persistence — so this epic is milestoned v1.1. Any individual slice can be pulled into v1.0 if a release-blocking issue comes to depend on it.
Acceptance criteria
Each captured series in its own table with retention + reset-safe delta handling.
Cadence throttles applied (per-worker ~5 min, network hourly; Tier-1 on the 30 s / external-sync cadence as noted).
What's persisted today
Only three things become history in SQLite (
build/dashboard/mining_dashboard/service/storage_service.py→_create_tables):historysharests,difficulty)kv_storelatest_datadict as onesnapshot_latest_datablob, overwritten every 30sEverything else the data loop fetches survives only as last-value inside that overwritten snapshot → no trend, gaps lost.
Design principles (shared across all sub-items)
historycolumns — independent retention, and avoids multiplyinghistoryrows for per-worker/per-series data.HISTORY_RETENTION_SEC+ the existing probabilistic prune (storage_service.py:240)._shares_to_recordpattern (data_service.py:176)./api/state; the actual charts/badges are tracked in the consuming feature issues (below).Captures
Tier 1 — high value, negligible/low cost
blocks_found/last_block_found(height) /last_block_ts(collector/pools.py:74). Detect thetotalBlocksFoundincrement (mirror_shares_to_record) →blocks(ts REAL PK, height INT, effort REAL). Blocks are the actual payout events; enables a found-blocks timeline + effort-per-block. ~rows per week. → feeds Flag outages / significant hashrate-loss events on the chart (+ feed Telegram/Healthchecks alerts) #99.data_service.py:116(_parse_proxy_summary). Already specced in Store share stats as time-series for reject-rate trends/charting #116 — design & implement there; listed here so the audit is complete. Enables reject-rate trends (the Simpler way to deploy #1 "something's wrong" signal).db_sizefromclient/monero/monero_client.py:82(already rides inmonero_sync) +collector/system.pyget_disk_usage(). Hourlydisk_growth(ts, monero_db_bytes, disk_used_gb, disk_total_gb). The chains grow monotonically and a full disk corrupts monerod mid-write; a growth trend forecasts "days until full." → extends No runtime disk guard: sync/log growth can silently fill the disk; dashboard has no free-disk metric #138 (closed) and feeds Surface setup/host warnings as dashboard badges (AVX2, HugePages, low disk/RAM) #104 (low-disk badge).kv_store(storage_service.py:290). Appendxvb_history(ts, avg_1h, avg_24h, fail_count, donation_fraction)on each external sync (~5 min,data_service.py:497). The donation controller steers off these — a credited-vs-routed history shows credit-factor & tier-holding over time.Tier 2 — valuable, throttle to avoid bloat
h15+ accepted / rejected) —data_service.py:40(_parse_proxy_list_worker). Per-worker data is lost entirely when a worker disconnects today. Newworker_history(ts, name, h15, accepted, rejected)at ~5 min cadence (not 30 s) + retention. Cardinality = workers × cadence → throttled & pruned. Intersects Dashboard: "Uptime" column is misleading for disconnected workers — show DOWN, and track real uptime in-dashboard #169 / Dashboard: stale/offline miners never leave the "Workers Alive" table — add a fall-off cutoff and/or a hide control #182 (v1.0 — but those are solvable with in-memorylast_activeand don't depend on this) and the per-worker stretch of Store share stats as time-series for reject-rate trends/charting #116. Do Remove dead known_workers persistence layer (orphaned by the proxy-sourced worker rewrite) #144 first (remove the deadknown_workerstable) so we don't build on orphaned code.collector/pools.pyget_network_stats/get_p2pool_stats. Hourlynetwork_history(...). Slow-moving → cheap at hourly; lets earnings estimates be back-tested against real difficulty.Explicitly NOT captured as a series (would bloat / low value)
collector/system.py) — high-frequency, low long-term value; keep as live gauges (hourly aggregates only if ever needed).get_stratum_stats) — large, redundant with the structured fields.latest_datasnapshot — correctly stays a single overwritten last-value blob.Relationships
known_workers/workerstable before addingworker_history.Milestone rationale
These captures back v1.1 trend/charting features (#116, #99, #104), and the v1.0 dashboard-accuracy issues (#169/#182) don't require persistence — so this epic is milestoned v1.1. Any individual slice can be pulled into v1.0 if a release-blocking issue comes to depend on it.
Acceptance criteria
/api/state.tests/service/coverage.worker_history.