From 4c6604db27f26998b72fd815b6bd1de5a3b08780 Mon Sep 17 00:00:00 2001 From: tv Date: Thu, 5 Nov 2026 00:56:24 +0100 Subject: own tree shape --- src/api/stats.rs | 25 +++++++++++++++++++++++++ src/api/stats/prometheus.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) (limited to 'src/api') diff --git a/src/api/stats.rs b/src/api/stats.rs index 5061ff7..3851ef7 100644 --- a/src/api/stats.rs +++ b/src/api/stats.rs @@ -187,6 +187,18 @@ struct TopologyView { stable: usize, neighbours: usize, stable_neighbours: usize, + /// Our own writer's tree (`swarm::tree::own_shape`); absent while we aren't in the + /// member list's graph. + own_tree: Option, +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +struct OwnTree { + members: usize, + depth: u32, + mean_depth: f64, + off_tree: usize, } #[derive(Debug, Serialize)] @@ -264,6 +276,18 @@ pub(crate) async fn get_stats(State(state): State, headers: HeaderMap) /// 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 own_tree = crate::swarm::tree::own_shape(state) + .await + .map(|shape| OwnTree { + members: shape.members, + depth: shape.depth, + mean_depth: if shape.members == 0 { + 0.0 + } else { + shape.hops as f64 / shape.members as f64 + }, + off_tree: shape.off, + }); let (heads, tier, remakes) = { let replica = state.doc.read().await; @@ -358,6 +382,7 @@ pub(crate) async fn collect(state: &AppState, list: &PeerListResponse) -> StatsR stable: s.stable, neighbours: s.neighbours, stable_neighbours: s.stable_neighbours, + own_tree, }), }, stability: StabilityStats { diff --git a/src/api/stats/prometheus.rs b/src/api/stats/prometheus.rs index 595466a..db3cef3 100644 --- a/src/api/stats/prometheus.rs +++ b/src/api/stats/prometheus.rs @@ -713,6 +713,32 @@ pub(super) fn render(stats: &StatsResponse, list: &PeerListResponse) -> String { "Current neighbours with the stable tier.", view.stable_neighbours as f64, ); + if let Some(tree) = &view.own_tree { + out.single( + "own_tree_members", + "gauge", + "Other members in this node's own writer's tree.", + tree.members as f64, + ); + out.single( + "own_tree_depth", + "gauge", + "Most hops from this node to a member along its own writer's tree.", + f64::from(tree.depth), + ); + out.single( + "own_tree_mean_depth", + "gauge", + "Mean hops from this node to a member along its own writer's tree.", + tree.mean_depth, + ); + out.single( + "own_tree_off_members", + "gauge", + "Members this node's own writer's tree doesn't reach (they get its writes by announcement).", + tree.off_tree as f64, + ); + } } let stability = &stats.stability; -- cgit v1.3.1