diff options
Diffstat (limited to 'src/api')
| -rw-r--r-- | src/api/peers.rs | 7 | ||||
| -rw-r--r-- | src/api/stats.rs | 4 | ||||
| -rw-r--r-- | src/api/stats/prometheus.rs | 35 |
3 files changed, 46 insertions, 0 deletions
diff --git a/src/api/peers.rs b/src/api/peers.rs index 0305647..7caaaf3 100644 --- a/src/api/peers.rs +++ b/src/api/peers.rs @@ -48,6 +48,8 @@ impl From<Epoch> for EpochInfo { #[serde(rename_all = "camelCase")] pub(crate) struct PeerStatus { public_key: String, + /// The name the peer gave itself in the member list, if any (not unique). + alias: Option<String>, validated_swarm: Option<String>, status: PeerLivenessStatus, handshake_complete: bool, @@ -87,6 +89,8 @@ pub(crate) struct ThroughputInfo { #[derive(Debug, Serialize, ToSchema)] #[serde(rename_all = "camelCase")] pub(crate) struct PeerListResponse { + /// Our own alias (`--alias`). + local_alias: Option<String>, local_epoch: EpochInfo, /// Number of heads of our document. Several heads are concurrent changes no later /// change has merged yet. @@ -125,6 +129,7 @@ pub(crate) async fn list_peers( let now = Instant::now(); let local_epoch = state.local_epoch(); + let mut aliases = crate::swarm::members::aliases(&state.doc.read().await.doc); let mut peers = Vec::with_capacity(snapshot.len()); for (public_key, peer_state_mutex) in snapshot { @@ -155,6 +160,7 @@ pub(crate) async fn list_peers( }; peers.push(PeerStatus { + alias: aliases.remove(&public_key), public_key, validated_swarm: ps.standing.swarm_id().map(str::to_owned), status, @@ -178,6 +184,7 @@ pub(crate) async fn list_peers( peers.sort_by(|a, b| a.public_key.cmp(&b.public_key)); let local_heads = state.doc.write().await.doc.get_heads().len(); Ok(Json(PeerListResponse { + local_alias: state.alias.clone(), local_epoch: local_epoch.into(), local_heads, peers, diff --git a/src/api/stats.rs b/src/api/stats.rs index b39e054..bc925ff 100644 --- a/src/api/stats.rs +++ b/src/api/stats.rs @@ -19,6 +19,8 @@ use crate::transport::traffic::PeerTraffic; #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub(crate) struct StatsResponse { + public_key: String, + alias: Option<String>, uptime_secs: u64, ready: bool, epoch: EpochInfo, @@ -147,6 +149,8 @@ async fn collect(state: &AppState) -> StatsResponse { } StatsResponse { + public_key: state.local_id().to_owned(), + alias: state.alias.clone(), uptime_secs: node.uptime.as_secs(), ready: state.is_ready().await, epoch: state.local_epoch().into(), diff --git a/src/api/stats/prometheus.rs b/src/api/stats/prometheus.rs index 16869f7..d29207c 100644 --- a/src/api/stats/prometheus.rs +++ b/src/api/stats/prometheus.rs @@ -68,6 +68,7 @@ fn flag(value: bool) -> f64 { /// What we show per peer. struct Peer { key: String, + alias: Option<String>, neighbour: bool, dormant: bool, last_seen_secs: Option<f64>, @@ -86,6 +87,7 @@ async fn peers(state: &AppState) -> Vec<Peer> { .iter() .map(|(key, peer_state)| (key.clone(), peer_state.clone())) .collect(); + 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); @@ -111,6 +113,7 @@ async fn peers(state: &AppState) -> Vec<Peer> { incidents: peer_state.incidents, rtt_secs, throughput, + alias: aliases.remove(&key), key, }); } @@ -139,6 +142,22 @@ fn traffic_series(traffic: &PeerTraffic) -> Vec<(&'static str, &'static str, Cou pub(super) async fn render(state: &AppState, stats: &StatsResponse) -> String { let mut out = Out::default(); + // Names for joining (`* on(peer) group_left(alias) continuum_peer_info`), kept out + // of the other series so a rename doesn't start new ones. + out.family( + "info", + "gauge", + "This node's public key and alias (always 1).", + ); + out.sample( + "info", + &[ + ("public_key", &stats.public_key), + ("alias", stats.alias.as_deref().unwrap_or("")), + ], + 1.0, + ); + out.single( "uptime_seconds", "gauge", @@ -342,6 +361,22 @@ pub(super) async fn render(state: &AppState, stats: &StatsResponse) -> String { let peers = peers(state).await; + out.family( + "peer_info", + "gauge", + "A peer's alias from the member list (always 1).", + ); + for peer in &peers { + out.sample( + "peer_info", + &[ + ("peer", &peer.key), + ("alias", peer.alias.as_deref().unwrap_or("")), + ], + 1.0, + ); + } + out.family("peer_neighbour", "gauge", "1 if the peer is a neighbour."); for peer in &peers { out.sample( |
