aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/api/dashboard/mod.rs6
-rw-r--r--src/api/stats.rs28
2 files changed, 19 insertions, 15 deletions
diff --git a/src/api/dashboard/mod.rs b/src/api/dashboard/mod.rs
index ad907ed..0a15570 100644
--- a/src/api/dashboard/mod.rs
+++ b/src/api/dashboard/mod.rs
@@ -257,8 +257,10 @@ impl Graph {
/// The snapshot: the node, its figures, its peers, and the map.
async fn build(state: &AppState, graph: &Graph) -> JsonValue {
- let stats = serde_json::to_value(super::stats::collect(state).await).unwrap_or_default();
- let peers = serde_json::to_value(super::peers::peer_list(state).await).unwrap_or_default();
+ // The peers once, for their list and the figures' totals over them.
+ let list = super::peers::peer_list(state).await;
+ let stats = serde_json::to_value(super::stats::collect(state, &list).await).unwrap_or_default();
+ let peers = serde_json::to_value(&list).unwrap_or_default();
let aliases = {
let replica = state.doc.read().await;
members::aliases(&replica.doc)
diff --git a/src/api/stats.rs b/src/api/stats.rs
index b9314e2..9e1b278 100644
--- a/src/api/stats.rs
+++ b/src/api/stats.rs
@@ -13,7 +13,7 @@ use std::collections::BTreeMap;
use serde::Serialize;
-use super::peers::EpochInfo;
+use super::peers::{EpochInfo, PeerListResponse, peer_list};
use crate::state::{AppState, Incidents};
use crate::swarm::{members, stability, topology};
use crate::transport::stats::TransportStats;
@@ -237,12 +237,12 @@ pub(crate) async fn get_relay_only_stats(
/// `GET /admin/stats`.
pub(crate) async fn get_stats(State(state): State<AppState>, headers: HeaderMap) -> Response {
- let stats = collect(&state).await;
+ let list = peer_list(&state).await;
+ let stats = collect(&state, &list).await;
let accept = headers
.get(header::ACCEPT)
.and_then(|value| value.to_str().ok());
if prometheus::wanted(accept) {
- let list = super::peers::peer_list(&state).await;
let body = prometheus::render(&stats, &list);
([(header::CONTENT_TYPE, prometheus::CONTENT_TYPE)], body).into_response()
} else {
@@ -250,8 +250,9 @@ pub(crate) async fn get_stats(State(state): State<AppState>, headers: HeaderMap)
}
}
-/// What `GET /admin/stats` answers as JSON, for others to show too (the dashboard).
-pub(crate) async fn collect(state: &AppState) -> StatsResponse {
+/// What `GET /admin/stats` answers as JSON, for others to show too (the dashboard); its
+/// totals over the peers from their list (`peer_list`), read once for both.
+pub(crate) async fn collect(state: &AppState, list: &PeerListResponse) -> StatsResponse {
let node = state.stats.snapshot();
let (heads, tier, remakes) = {
@@ -270,16 +271,17 @@ pub(crate) async fn collect(state: &AppState) -> StatsResponse {
let (connected_fraction, observed) = stability::measured(state);
let mut incidents = Incidents::default();
- let mut last_from_neighbour: Option<tokio::time::Instant> = None;
+ let mut last_from_neighbour_secs: Option<u64> = None;
let mut diverged_peers = 0;
- for (peer, peer_state) in state.peers_snapshot().await {
- let peer_state = peer_state.lock().await;
- incidents.add(&peer_state.incidents);
- if peer_state.diverged_since.is_some() {
+ for peer in list.peers.values() {
+ incidents.add(&peer.incidents);
+ if peer.diverged_for_secs.is_some() {
diverged_peers += 1;
}
- if topology::is_neighbour(state, &peer) {
- last_from_neighbour = last_from_neighbour.max(peer_state.last_sync_rx);
+ if peer.neighbour
+ && let Some(secs) = peer.last_sync_secs_ago
+ {
+ last_from_neighbour_secs = Some(last_from_neighbour_secs.map_or(secs, |s| s.min(secs)));
}
}
@@ -315,7 +317,7 @@ pub(crate) async fn collect(state: &AppState) -> StatsResponse {
archived_epochs: remakes.archived_epochs,
},
sync: SyncStats {
- last_from_neighbour_secs: last_from_neighbour.map(|at| at.elapsed().as_secs()),
+ last_from_neighbour_secs,
diverged_peers,
largest_received_bytes: node.largest_sync_received,
},