Skip to content

feat(monitoring): opt-in per-SV1-client hashrate metric - #803

Open
gimballock wants to merge 2 commits into
stratum-mining:mainfrom
marafoundation:sv1-per-client-metrics
Open

feat(monitoring): opt-in per-SV1-client hashrate metric#803
gimballock wants to merge 2 commits into
stratum-mining:mainfrom
marafoundation:sv1-per-client-metrics

Conversation

@gimballock

Copy link
Copy Markdown
Contributor

The tProxy exposes only sv1_clients_total and sv1_hashrate_total, so Prometheus cannot answer "what was this miner's hashrate over the last six hours." The per-client data is already collected on every refresh and then dropped: refresh() populates sv1_clients, but update_metrics() consumes only the aggregates. This emits a series from data already in hand.

SV1 miners behind the translator are typically the on-premise machines an operator most needs to inspect individually. /api/v1/sv1/clients answers "what is this miner doing now" well, but has no history, so that question currently has no answer on any surface.

Changes

  • sv1_client_hashrate{user_identity}, sourced from the existing sv1_clients snapshot.
  • Opt-in. Registered only via PrometheusMetrics::with_sv1_per_client, selected by a new per_client_metrics flag on with_sv1_monitoring, driven by a monitoring_sv1_per_client_metrics config field on the translator that defaults to off. Existing deployments are unaffected, and the JSON API serves per-client state either way.
  • Documented in monitoring/README.md and, commented out, in the tproxy config examples.

Design notes

Label choice. user_identity (the SV1 username) rather than client_id, because client_id changes on every reconnect and would fragment a miner's history into a new series per connection. Connections sharing a username are summed rather than clobbering one another, since that is the operator-meaningful answer.

Series are reaped. Departed miners are removed on the next refresh through the existing stale-label mechanism, so a disconnect does not leak a series. Covered by a test that asserts the series set is empty after all miners disconnect — this is the part most likely to regress silently.

Cardinality. Opt-in is the only bound here. A tighter mechanism (top-N by hashrate, or an allowlist) can layer on if wanted; I left it out because opt-in already prevents an unbounded default and I would rather not invent a bounding policy unilaterally. Happy to add one if you'd prefer it in this PR.

Caveat worth documenting

The per-client hashrate is vardiff-driven, and #262 records it going stale when enable_vardiff = false and the upstream adjusts difficulty via SetTarget. This metric inherits that, so it is an estimate rather than measured throughput.

Verified

stratum-apps 110/110 with monitoring and 120/120 with asic-rs-telemetry (the translator's default); translator_sv2 48/48; integration-tests and pool still compile; clippy and fmt clean. Config knob deserialization is covered by a test asserting both the default-off and explicitly-enabled cases.

🤖 Generated with Claude Code

Eric Price and others added 2 commits August 24, 2026 11:01
The tProxy exposed only `sv1_clients_total` and `sv1_hashrate_total`, so
Prometheus could not answer "what was this miner's hashrate over the last
six hours". The per-client data was already collected on every refresh —
`refresh()` populates `sv1_clients` — and then dropped, because
`update_metrics()` consumed only the aggregates.

Emit `sv1_client_hashrate{user_identity}` from that existing data.

Opt-in via `PrometheusMetrics::with_sv1_per_client`, because the series
count scales with connected miners; `with_sv1_monitoring` takes a flag to
select it. The JSON API serves per-client state either way.

Labelled by SV1 username rather than a connection id, so a reconnecting
miner continues the same series. Connections sharing a username are summed
rather than clobbering each other. Series for departed miners are removed
on the next refresh via the existing stale-label mechanism, so a miner
disconnecting does not leak a series.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Gates the per-SV1-client Prometheus series added in the previous commit.
Defaults to off, so existing deployments are unaffected and an operator
opts in only where the miner population is known to be bounded.

Documented in the config examples, commented out, alongside the existing
monitoring settings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gimballock
gimballock marked this pull request as ready for review August 24, 2026 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant