feat: mining efficiency panels, and say what they cannot measure
deploy / fetch (push) Successful in 17s
deploy / deploy-node (bob.hanzalova.internal, 0x134e73f06fa9bdb1dbfa909e149c563f5860ceb71a0e7307918f7033970edf59, benjy.hanzalova.internal, --public-addr /dns4/nh.thgttg.com/tcp/30333) (push) Successful in 31s
deploy / deploy-miner (1, benjy.hanzalova.internal, bob.hanzalova.internal) (push) Successful in 41s
deploy / deploy-metrics (push) Successful in 9s

Adds a Mining efficiency row: mining rounds started per minute, hashes
per mining round, and active jobs over time.

These are proxies, not the answer. Neither binary exports what the
question actually needs -- quantus-node has no difficulty metric and no
authored-block counter (substrate_proposer_block_constructed counts
proposals constructed, not rounds won), and quantus-miner has no
solutions-found counter. So authored-blocks-vs-expected-share cannot be
plotted, and a panel implying otherwise would be worse than none.

A text panel on the row states that plainly rather than leaving someone
to infer a conclusion the data does not support. lair/quantus#1 tracks
closing the gap -- a chain-query exporter counting blocks credited to
the reward address is the cheapest route -- and the experiments that
depend on it.
This commit is contained in:
Rob Thijssen
2026-08-31 19:05:35 +03:00
parent 2cd478646f
commit bbe29caafe
2 changed files with 194 additions and 1 deletions
+186 -1
View File
@@ -9,7 +9,7 @@
],
"timezone": "browser",
"schemaVersion": 39,
"version": 1,
"version": 2,
"refresh": "30s",
"time": {
"from": "now-6h",
@@ -1073,6 +1073,191 @@
}
},
"description": "Counter derivative \u2014 the honest check that work is being done, independent of the reported gauge."
},
{
"type": "row",
"title": "Mining efficiency",
"collapsed": false,
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 33
},
"panels": []
},
{
"type": "timeseries",
"title": "Mining rounds started (per min)",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"h": 8,
"w": 8,
"x": 0,
"y": 34
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(rate(substrate_proposer_block_constructed_count{job=\"quantus-node\"}[5m])) * 60",
"legendFormat": "rounds/min",
"range": true,
"refId": "A"
}
],
"fieldConfig": {
"defaults": {
"custom": {
"lineWidth": 2,
"fillOpacity": 8,
"showPoints": "never"
},
"color": {
"mode": "palette-classic"
},
"unit": "none"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"description": "Each new best tip makes the node construct a fresh block proposal and hand the miner a new job. Once synced this should track the network's block rate \u2014 about 10/min at a 6s target. Persistently below that means the node is learning about tips late, which is the connectivity effect peer count is supposed to improve. Near zero while syncing is normal: the node does not author until it is caught up."
},
{
"type": "timeseries",
"title": "Hashes per mining round",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"h": 8,
"w": 8,
"x": 8,
"y": 34
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "sum(rate(miner_hashes_total{job=\"quantus-miner\"}[5m])) / sum(rate(substrate_proposer_block_constructed_count{job=\"quantus-node\"}[5m]))",
"legendFormat": "hashes/round",
"range": true,
"refId": "A"
}
],
"fieldConfig": {
"defaults": {
"custom": {
"lineWidth": 2,
"fillOpacity": 8,
"showPoints": "never"
},
"color": {
"mode": "palette-classic"
},
"unit": "short"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"description": "Work completed per round. Expected hashes per block is the network difficulty, so hashes-per-round \u00f7 difficulty is the per-round win probability \u2014 but difficulty is NOT exported by either binary, so that division cannot be plotted. Absolute value is still useful as a trend: a fall means rounds are being cut short by incoming tips."
},
{
"type": "timeseries",
"title": "Active jobs",
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"gridPos": {
"h": 8,
"w": 8,
"x": 16,
"y": 34
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"editorMode": "code",
"expr": "miner_active_jobs{job=\"quantus-miner\"}",
"legendFormat": "{{instance}}",
"range": true,
"refId": "A"
}
],
"fieldConfig": {
"defaults": {
"custom": {
"lineWidth": 2,
"fillOpacity": 8,
"showPoints": "never"
},
"color": {
"mode": "palette-classic"
},
"unit": "none"
},
"overrides": []
},
"options": {
"legend": {
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"description": "Jobs in flight. Should be continuously non-zero once the node is synced. Gaps mean the miner is idle \u2014 either the node has no work, or the QUIC link dropped."
},
{
"type": "text",
"title": "What this row cannot tell you yet",
"gridPos": {
"h": 6,
"w": 24,
"x": 0,
"y": 42
},
"options": {
"mode": "markdown",
"content": "**Blocks actually authored is not observable from these exporters.**\n\n`quantus-node` exports no difficulty metric and no authored-block counter \u2014 `substrate_proposer_block_constructed` counts proposals *constructed*, not rounds *won*. `quantus-miner` exports no solutions-found counter either (`miner_hashes_total`, `miner_hash_rate`, `miner_active_jobs`, worker/device gauges, and nothing else).\n\nSo the question worth answering \u2014 *do we win the share of blocks our hashrate predicts?* \u2014 cannot currently be plotted. That ratio is the real measure of orphan and stale-work loss, and therefore the only honest test of whether tuning peer count or anything else helped.\n\nClosing that gap needs one of: an upstream metric for difficulty and blocks authored, a log-derived exporter, or a periodic chain query counting blocks credited to the reward address. Tracked in the repo's issues \u2014 read that before drawing conclusions from the panels above."
}
}
]
}
+8
View File
@@ -97,6 +97,14 @@ instead of every project editing one file, and `grafana.container` gained a
dashboards bind mount — it previously mounted only the datasource. Both are
additive, guarded, and back up what they touch.
**What the dashboard cannot tell you:** neither binary exports a difficulty
metric or an authored-block counter, and the miner exports no solutions-found
counter — so "do we win the share of blocks our hashrate predicts?", the only
honest measure of orphan and stale-work loss, is not plottable today. The
"Mining efficiency" row shows the measurable proxies and says so explicitly.
Closing that gap, and the experiments that depend on it, are tracked in
[issue #1](https://git.lair.cafe/lair/quantus/issues/1).
The dashboard is provisioned with `allowUiUpdates: false`: edit the JSON here and
redeploy, so a browser tweak cannot silently diverge from source.