admin api: report avilable space numerically in GetClusterStatistics

This commit is contained in:
Alex Auvolat
2026-03-06 09:49:00 +01:00
committed by Alex
parent 836657565e
commit 03e6020c6b
3 changed files with 66 additions and 27 deletions
+14
View File
@@ -282,8 +282,22 @@ pub struct GetClusterHealthResponse {
pub struct GetClusterStatisticsRequest;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct GetClusterStatisticsResponse {
/// cluster statistics as a free-form string, kept for compatibility with nodes
/// running older v2.x versions of garage
pub freeform: String,
/// available storage space for object data in the entire cluster, in bytes
#[serde(default)]
pub data_avail: u64,
/// available storage space for object metadata in the entire cluster, in bytes
#[serde(default)]
pub metadata_avail: u64,
/// true if the available storage space statistics are imprecise due to missing
/// information of disconnected nodes. When this is the case, the actual
/// space available in the cluster might be lower than the reported values.
#[serde(default)]
pub incomplete_info: bool,
}
// ---- ConnectClusterNodes ----
+33 -25
View File
@@ -231,33 +231,41 @@ impl RequestHandler for GetClusterStatisticsRequest {
.map(|c| c.0 / *parts)
})
.collect::<Vec<_>>();
if !meta_part_avail.is_empty() && !data_part_avail.is_empty() {
let meta_avail =
bytesize::ByteSize(meta_part_avail.iter().min().unwrap() * (1 << PARTITION_BITS));
let data_avail =
bytesize::ByteSize(data_part_avail.iter().min().unwrap() * (1 << PARTITION_BITS));
writeln!(
&mut ret,
"\nEstimated available storage space cluster-wide (might be lower in practice):"
)
.unwrap();
if meta_part_avail.len() < node_partition_count.len()
|| data_part_avail.len() < node_partition_count.len()
{
ret += &format_table_to_string(vec![
format!(" data: < {}", data_avail),
format!(" metadata: < {}", meta_avail),
]);
writeln!(&mut ret, "A precise estimate could not be given as information is missing for some storage nodes.").unwrap();
} else {
ret += &format_table_to_string(vec![
format!(" data: {}", data_avail),
format!(" metadata: {}", meta_avail),
]);
}
let metadata_avail: u64 =
meta_part_avail.iter().min().unwrap_or(&0) * (1 << PARTITION_BITS);
let data_avail: u64 = data_part_avail.iter().min().unwrap_or(&0) * (1 << PARTITION_BITS);
let metadata_avail_str = bytesize::ByteSize(metadata_avail);
let data_avail_str = bytesize::ByteSize(data_avail);
let incomplete_info = meta_part_avail.len() < node_partition_count.len()
|| data_part_avail.len() < node_partition_count.len();
writeln!(
&mut ret,
"\nEstimated available storage space cluster-wide (might be lower in practice):"
)
.unwrap();
if incomplete_info {
ret += &format_table_to_string(vec![
format!(" data: < {}", data_avail_str),
format!(" metadata: < {}", metadata_avail_str),
]);
writeln!(&mut ret, "A precise estimate could not be given as information is missing for some storage nodes.").unwrap();
} else {
ret += &format_table_to_string(vec![
format!(" data: {}", data_avail_str),
format!(" metadata: {}", metadata_avail_str),
]);
}
Ok(GetClusterStatisticsResponse { freeform: ret })
Ok(GetClusterStatisticsResponse {
freeform: ret,
metadata_avail,
data_avail,
incomplete_info,
})
}
}