From dfd10291ad24853fc26d90858a722d70752cce92 Mon Sep 17 00:00:00 2001 From: Rob Thijssen Date: Thu, 3 Sep 2026 16:10:48 +0300 Subject: [PATCH] arena: cumulative authorship counter so the leaderboard follows the time range quantus_blocks_authored is a rolling window by block count (3600 blocks) served as a gauge, so the leaderboard panel ignored Grafana's time picker. Add quantus_blocks_authored_total, cumulative since exporter start and not capped to top N (a counter that comes and goes loses increments; the label set is bounded by distinct miners seen), and query the panel as increase() over $__range. The windowed gauge stays for the fixed view. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01CBgs2nSi4H2mdh8kD8vMX5 --- asset/arena/quantus-arena-exporter.py | 14 ++++++++++++++ asset/grafana/quantus.json | 8 ++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/asset/arena/quantus-arena-exporter.py b/asset/arena/quantus-arena-exporter.py index 2c8270c..0bd4747 100755 --- a/asset/arena/quantus-arena-exporter.py +++ b/asset/arena/quantus-arena-exporter.py @@ -325,6 +325,12 @@ class Arena: # while the node is catching up: it ingests historical blocks at import # speed, so "the last hour" can contain half a million blocks. self.blocks = deque(maxlen=window_blocks) # (height, preimage) + # Cumulative per-preimage count since the exporter started, for panels + # that follow the dashboard's time range (increase() over $__range). + # The windowed gauge above cannot do that: it is always the last N + # blocks. Not capped to top N: a counter that appears and disappears + # loses increments, and the label set is bounded by distinct miners. + self.authored_total = {} # Tip observations only — used for the block interval, which is real # elapsed time between blocks and therefore only valid at the tip. self.tip_samples = deque(maxlen=200) # (unix_ts, height) @@ -352,6 +358,7 @@ class Arena: with self.lock: self.blocks.append((height, pre)) self.blocks_seen += 1 + self.authored_total[pre] = self.authored_total.get(pre, 0) + 1 if at_tip: self.tip_samples.append((time.time(), height)) @@ -494,6 +501,13 @@ class Arena: shown = sum(keep.values()) out.append(f"quantus_blocks_authored{{preimage=\"other\",self=\"false\"}} {total - shown}") + out.append("# HELP quantus_blocks_authored_total Blocks observed authored since the exporter " + "started, by reward preimage. Cumulative; use increase() over a range.") + out.append("# TYPE quantus_blocks_authored_total counter") + for pre, n in sorted(self.authored_total.items(), key=lambda kv: kv[1], reverse=True): + is_self = "true" if pre == self.self_preimage else "false" + out.append(f'quantus_blocks_authored_total{{preimage="{pre}",self="{is_self}"}} {n}') + if self.balance is not None and self.decimals is not None: free, reserved, frozen, nonce = self.balance scale = 10 ** self.decimals diff --git a/asset/grafana/quantus.json b/asset/grafana/quantus.json index 27409c8..e00ca0d 100644 --- a/asset/grafana/quantus.json +++ b/asset/grafana/quantus.json @@ -9,7 +9,7 @@ ], "timezone": "browser", "schemaVersion": 39, - "version": 11, + "version": 12, "refresh": "30s", "time": { "from": "now-6h", @@ -1705,7 +1705,7 @@ }, { "type": "table", - "title": "Authorship leaderboard", + "title": "Authorship leaderboard (dashboard time range)", "datasource": { "type": "prometheus", "uid": "prometheus" @@ -1716,7 +1716,7 @@ "x": 0, "y": 62 }, - "description": "Blocks authored per reward preimage, decoded from each header's PreRuntime digest \u2014 every miner on the network, no indexer needed.\n\nThe window is a BLOCK COUNT, capped at 3600 (~12h at the current interval), not a time range: a time window is meaningless while the node catches up, since it ingests history at import speed. It refills from empty after an arena-exporter restart, so the panels to the right show how full it actually is \u2014 read those before comparing shares.\n\nThe dashboard time picker does NOT change this window; the exporter owns it.", + "description": "Blocks observed authored within the selected time range, by reward preimage, from the cumulative counter quantus_blocks_authored_total. Counts exist from the moment the exporter started exporting it and within Prometheus retention; increase() extrapolates across scrape gaps, so treat the last digit as approximate. The fixed 3600-block window is quantus_blocks_authored.", "targets": [ { "datasource": { @@ -1725,7 +1725,7 @@ }, "editorMode": "code", "refId": "A", - "expr": "topk(20, quantus_blocks_authored)", + "expr": "sort_desc(topk(20, round(increase(quantus_blocks_authored_total[$__range]))))", "instant": true, "range": false, "format": "table" -- 2.52.0