From 987ba0ffc6a272d5b426e6b91da18f49b480537a Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 31 Oct 2026 04:10:37 +0100 Subject: prometheus: build per-peer series from /peers --- src/api/stats/prometheus.rs | 70 +++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 44 deletions(-) (limited to 'src/api/stats') diff --git a/src/api/stats/prometheus.rs b/src/api/stats/prometheus.rs index 01f1619..9180d9d 100644 --- a/src/api/stats/prometheus.rs +++ b/src/api/stats/prometheus.rs @@ -4,11 +4,9 @@ use std::fmt::Write; -use tokio::time::Instant; - use super::StatsResponse; -use crate::locks::MutexExt; -use crate::state::{AppState, Incidents, Liveness}; +use crate::api::peers::{PeerListResponse, PeerLivenessStatus}; +use crate::state::Incidents; use crate::transport::Destination; use crate::transport::stats::{Reachability, TransportStats}; use crate::transport::traffic::{ByKind, Counter, PeerTraffic}; @@ -128,43 +126,26 @@ struct Peer { destination: Option, } -async fn peers(state: &AppState) -> Vec { - let now = Instant::now(); - let snapshot = state.peers_snapshot().await; - let mut aliases = crate::swarm::members::aliases(&state.doc.read().await.doc); - let mut peers = Vec::with_capacity(snapshot.len()); - for (key, peer_state) in snapshot { - let neighbour = crate::swarm::topology::is_neighbour(state, &key); - let throughput = state - .throughput - .lock_or_recover() - .get(&key) - .map(|estimate| estimate.bytes_per_sec); - let traffic = state.traffic.peer(&key).unwrap_or_default(); - let peer_state = peer_state.lock().await; - peers.push(Peer { - neighbour, - unknown: peer_state.liveness == Liveness::Unknown, - dormant: matches!(peer_state.liveness, Liveness::Dormant { .. }), - last_seen_secs: peer_state - .last_seen - .map(|t| now.saturating_duration_since(t).as_secs_f64()), - last_sync_secs: peer_state - .last_sync_rx - .map(|t| now.saturating_duration_since(t).as_secs_f64()), - diverged_secs: peer_state - .diverged_since - .map(|t| now.saturating_duration_since(t).as_secs_f64()), - traffic, - incidents: peer_state.incidents, - throughput, - alias: aliases.remove(&key), - destination: state.transport.destination(&key), - key, - }); - } - peers.sort_by(|a, b| a.key.cmp(&b.key)); - peers +/// The rows of `/peers` (`peers::peer_list`), as the series need them. +fn peers(list: &PeerListResponse) -> Vec { + let secs = |secs: Option| secs.map(|secs| secs as f64); + list.peers + .iter() + .map(|(key, peer)| Peer { + key: key.clone(), + alias: peer.alias.clone(), + neighbour: peer.neighbour, + unknown: matches!(peer.status, PeerLivenessStatus::Unknown), + dormant: matches!(peer.status, PeerLivenessStatus::Dormant), + last_seen_secs: secs(peer.last_seen_secs_ago), + last_sync_secs: secs(peer.last_sync_secs_ago), + diverged_secs: secs(peer.diverged_for_secs), + traffic: peer.traffic, + incidents: peer.incidents, + throughput: peer.sync_throughput.as_ref().map(|t| t.bytes_per_sec), + destination: peer.destination.clone(), + }) + .collect() } /// Every (direction, kind, counter) of `traffic`. @@ -399,7 +380,8 @@ pub(super) fn render_relay_only(stats: &super::RelayOnlyStats) -> String { /// A per-peer incident counter: its name, its help and how to read it. type IncidentSeries = (&'static str, &'static str, fn(&Incidents) -> f64); -pub(super) async fn render(state: &AppState, stats: &StatsResponse) -> String { +/// `stats` and `list` (`/peers`) as series: nothing read anew. +pub(super) fn render(stats: &StatsResponse, list: &PeerListResponse) -> String { let mut out = Out::default(); // Names for joining (`* on(peer) group_left(alias) continuum_peer_info`), kept out @@ -430,7 +412,7 @@ pub(super) async fn render(state: &AppState, stats: &StatsResponse) -> String { "epoch_generation", "gauge", "Generation of the local epoch (remakes so far).", - state.local_epoch().generation as f64, + stats.epoch.generation as f64, ); let document = &stats.document; @@ -807,7 +789,7 @@ pub(super) async fn render(state: &AppState, stats: &StatsResponse) -> String { transports(&mut out, &stats.transports); - let peers = peers(state).await; + let peers = peers(list); out.family( "peer_info", -- cgit v1.3.1