mirror of
https://github.com/kharonsec/garage.git
synced 2026-04-25 20:44:55 +02:00
admin api: export node statistics as structured json
This commit is contained in:
@@ -22,8 +22,12 @@ impl RequestHandler for LocalGetNodeInfoRequest {
|
||||
garage: &Arc<Garage>,
|
||||
_admin: &Admin,
|
||||
) -> Result<LocalGetNodeInfoResponse, Error> {
|
||||
let sys_status = garage.system.local_status();
|
||||
let hostname = sys_status.hostname.unwrap_or_default().to_string();
|
||||
|
||||
Ok(LocalGetNodeInfoResponse {
|
||||
node_id: hex::encode(garage.system.id),
|
||||
hostname,
|
||||
garage_version: garage_util::version::garage_version().to_string(),
|
||||
garage_features: garage_util::version::garage_features()
|
||||
.map(|features| features.iter().map(ToString::to_string).collect()),
|
||||
@@ -57,46 +61,58 @@ impl RequestHandler for LocalGetNodeStatisticsRequest {
|
||||
) -> Result<LocalGetNodeStatisticsResponse, Error> {
|
||||
let sys_status = garage.system.local_status();
|
||||
|
||||
let hostname = sys_status.hostname.unwrap_or_default().to_string();
|
||||
let garage_version = garage_util::version::garage_version().to_string();
|
||||
let garage_features = garage_util::version::garage_features()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<String>>();
|
||||
let rustc_version = garage_util::version::rust_version().to_string();
|
||||
let db_engine_descr = garage.db.engine();
|
||||
|
||||
let mut ret = format_table_to_string(vec![
|
||||
format!("Node ID:\t{:?}", garage.system.id),
|
||||
format!("Hostname:\t{}", sys_status.hostname.unwrap_or_default(),),
|
||||
format!(
|
||||
"Garage version:\t{}",
|
||||
garage_util::version::garage_version(),
|
||||
),
|
||||
format!(
|
||||
"Garage features:\t{}",
|
||||
garage_util::version::garage_features()
|
||||
.map(|list| list.join(", "))
|
||||
.unwrap_or_else(|| "(unknown)".into()),
|
||||
),
|
||||
format!(
|
||||
"Rust compiler version:\t{}",
|
||||
garage_util::version::rust_version(),
|
||||
),
|
||||
format!("Database engine:\t{}", garage.db.engine()),
|
||||
format!("Hostname:\t{}", hostname),
|
||||
format!("Garage version:\t{}", garage_version),
|
||||
format!("Garage features:\t{}", garage_features.join(", ")),
|
||||
format!("Rust compiler version:\t{}", rustc_version),
|
||||
format!("Database engine:\t{}", db_engine_descr),
|
||||
]);
|
||||
|
||||
// Gather table statistics
|
||||
let mut table = vec![" Table\tItems\tMklItems\tMklTodo\tInsQueue\tGcTodo".into()];
|
||||
table.push(gather_table_stats(&garage.admin_token_table)?);
|
||||
table.push(gather_table_stats(&garage.bucket_table)?);
|
||||
table.push(gather_table_stats(&garage.bucket_alias_table)?);
|
||||
table.push(gather_table_stats(&garage.key_table)?);
|
||||
|
||||
table.push(gather_table_stats(&garage.object_table)?);
|
||||
table.push(gather_table_stats(&garage.object_counter_table.table)?);
|
||||
table.push(gather_table_stats(&garage.mpu_table)?);
|
||||
table.push(gather_table_stats(&garage.mpu_counter_table.table)?);
|
||||
table.push(gather_table_stats(&garage.version_table)?);
|
||||
table.push(gather_table_stats(&garage.block_ref_table)?);
|
||||
let mut table_stats = vec![
|
||||
gather_table_stats(&garage.admin_token_table)?,
|
||||
gather_table_stats(&garage.bucket_table)?,
|
||||
gather_table_stats(&garage.bucket_alias_table)?,
|
||||
gather_table_stats(&garage.key_table)?,
|
||||
gather_table_stats(&garage.object_table)?,
|
||||
gather_table_stats(&garage.object_counter_table.table)?,
|
||||
gather_table_stats(&garage.mpu_table)?,
|
||||
gather_table_stats(&garage.mpu_counter_table.table)?,
|
||||
gather_table_stats(&garage.version_table)?,
|
||||
gather_table_stats(&garage.block_ref_table)?,
|
||||
];
|
||||
|
||||
#[cfg(feature = "k2v")]
|
||||
{
|
||||
table.push(gather_table_stats(&garage.k2v.item_table)?);
|
||||
table.push(gather_table_stats(&garage.k2v.counter_table.table)?);
|
||||
table_stats.push(gather_table_stats(&garage.k2v.item_table)?);
|
||||
table_stats.push(gather_table_stats(&garage.k2v.counter_table.table)?);
|
||||
}
|
||||
|
||||
// Gather table statistics
|
||||
let mut table = vec![" Table\tItems\tMklItems\tMklTodo\tInsQueue\tGcTodo".into()];
|
||||
table.extend(table_stats.iter().map(|ts| {
|
||||
format!(
|
||||
" {}\t{}\t{}\t{}\t{}\t{}",
|
||||
ts.table_name,
|
||||
ts.items,
|
||||
ts.merkle_items,
|
||||
ts.merkle_queue_len,
|
||||
ts.insert_queue_len,
|
||||
ts.gc_queue_len,
|
||||
)
|
||||
}));
|
||||
|
||||
write!(
|
||||
&mut ret,
|
||||
"\nTable stats:\n{}",
|
||||
@@ -104,46 +120,52 @@ impl RequestHandler for LocalGetNodeStatisticsRequest {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let block_manager_stats = NodeBlockManagerStats {
|
||||
rc_entries: garage.block_manager.rc_approximate_len()? as u64,
|
||||
resync_queue_len: garage.block_manager.resync.queue_approximate_len()? as u64,
|
||||
resync_errors: garage.block_manager.resync.errors_approximate_len()? as u64,
|
||||
};
|
||||
|
||||
// Gather block manager statistics
|
||||
writeln!(&mut ret, "\nBlock manager stats:").unwrap();
|
||||
let rc_len = garage.block_manager.rc_approximate_len()?.to_string();
|
||||
|
||||
ret += &format_table_to_string(vec![
|
||||
format!(" number of RC entries:\t{} (~= number of blocks)", rc_len),
|
||||
format!(
|
||||
" number of RC entries:\t{} (~= number of blocks)",
|
||||
block_manager_stats.rc_entries
|
||||
),
|
||||
format!(
|
||||
" resync queue length:\t{}",
|
||||
garage.block_manager.resync.queue_approximate_len()?
|
||||
block_manager_stats.resync_queue_len,
|
||||
),
|
||||
format!(
|
||||
" blocks with resync errors:\t{}",
|
||||
garage.block_manager.resync.errors_approximate_len()?
|
||||
block_manager_stats.resync_errors
|
||||
),
|
||||
]);
|
||||
|
||||
Ok(LocalGetNodeStatisticsResponse { freeform: ret })
|
||||
Ok(LocalGetNodeStatisticsResponse {
|
||||
freeform: ret,
|
||||
table_stats,
|
||||
block_manager_stats,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn gather_table_stats<F, R>(t: &Arc<Table<F, R>>) -> Result<String, Error>
|
||||
fn gather_table_stats<F, R>(t: &Arc<Table<F, R>>) -> Result<NodeTableStats, Error>
|
||||
where
|
||||
F: TableSchema + 'static,
|
||||
R: TableReplication + 'static,
|
||||
{
|
||||
let data_len = t
|
||||
.data
|
||||
.store
|
||||
.approximate_len()
|
||||
.map_err(GarageError::from)?
|
||||
.to_string();
|
||||
let mkl_len = t.merkle_updater.merkle_tree_approximate_len()?.to_string();
|
||||
let data_len = t.data.store.approximate_len().map_err(GarageError::from)?;
|
||||
let mkl_len = t.merkle_updater.merkle_tree_approximate_len()?;
|
||||
|
||||
Ok(format!(
|
||||
" {}\t{}\t{}\t{}\t{}\t{}",
|
||||
F::TABLE_NAME,
|
||||
data_len,
|
||||
mkl_len,
|
||||
t.merkle_updater.todo_approximate_len()?,
|
||||
t.data.insert_queue_approximate_len()?,
|
||||
t.data.gc_todo_approximate_len()?
|
||||
))
|
||||
Ok(NodeTableStats {
|
||||
table_name: F::TABLE_NAME.to_string(),
|
||||
items: data_len as u64,
|
||||
merkle_items: mkl_len as u64,
|
||||
merkle_queue_len: t.merkle_updater.todo_approximate_len()? as u64,
|
||||
insert_queue_len: t.data.insert_queue_approximate_len()? as u64,
|
||||
gc_queue_len: t.data.gc_todo_approximate_len()? as u64,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user