cli: prettier table in garage stats
This commit is contained in:
parent
d7f90cabb0
commit
d6040e32a6
7 changed files with 93 additions and 39 deletions
|
@ -318,6 +318,11 @@ impl BlockManager {
|
||||||
Ok(self.rc.rc.len()?)
|
Ok(self.rc.rc.len()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get number of items in the refcount table
|
||||||
|
pub fn rc_fast_len(&self) -> Result<Option<usize>, Error> {
|
||||||
|
Ok(self.rc.rc.fast_len()?)
|
||||||
|
}
|
||||||
|
|
||||||
/// Send command to start/stop/manager scrub worker
|
/// Send command to start/stop/manager scrub worker
|
||||||
pub async fn send_scrub_command(&self, cmd: ScrubWorkerCommand) {
|
pub async fn send_scrub_command(&self, cmd: ScrubWorkerCommand) {
|
||||||
let _ = self.tx_scrub_command.send(cmd).await;
|
let _ = self.tx_scrub_command.send(cmd).await;
|
||||||
|
|
|
@ -181,6 +181,10 @@ impl Tree {
|
||||||
pub fn len(&self) -> Result<usize> {
|
pub fn len(&self) -> Result<usize> {
|
||||||
self.0.len(self.1)
|
self.0.len(self.1)
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn fast_len(&self) -> Result<Option<usize>> {
|
||||||
|
self.0.fast_len(self.1)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn first(&self) -> Result<Option<(Value, Value)>> {
|
pub fn first(&self) -> Result<Option<(Value, Value)>> {
|
||||||
|
@ -323,6 +327,9 @@ pub(crate) trait IDb: Send + Sync {
|
||||||
|
|
||||||
fn get(&self, tree: usize, key: &[u8]) -> Result<Option<Value>>;
|
fn get(&self, tree: usize, key: &[u8]) -> Result<Option<Value>>;
|
||||||
fn len(&self, tree: usize) -> Result<usize>;
|
fn len(&self, tree: usize) -> Result<usize>;
|
||||||
|
fn fast_len(&self, _tree: usize) -> Result<Option<usize>> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
fn insert(&self, tree: usize, key: &[u8], value: &[u8]) -> Result<Option<Value>>;
|
fn insert(&self, tree: usize, key: &[u8], value: &[u8]) -> Result<Option<Value>>;
|
||||||
fn remove(&self, tree: usize, key: &[u8]) -> Result<Option<Value>>;
|
fn remove(&self, tree: usize, key: &[u8]) -> Result<Option<Value>>;
|
||||||
|
|
|
@ -121,6 +121,10 @@ impl IDb for LmdbDb {
|
||||||
Ok(tree.len(&tx)?.try_into().unwrap())
|
Ok(tree.len(&tx)?.try_into().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fast_len(&self, tree: usize) -> Result<Option<usize>> {
|
||||||
|
Ok(Some(self.len(tree)?))
|
||||||
|
}
|
||||||
|
|
||||||
fn insert(&self, tree: usize, key: &[u8], value: &[u8]) -> Result<Option<Value>> {
|
fn insert(&self, tree: usize, key: &[u8], value: &[u8]) -> Result<Option<Value>> {
|
||||||
let tree = self.get_tree(tree)?;
|
let tree = self.get_tree(tree)?;
|
||||||
let mut tx = self.db.write_txn()?;
|
let mut tx = self.db.write_txn()?;
|
||||||
|
|
|
@ -144,6 +144,10 @@ impl IDb for SqliteDb {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fast_len(&self, tree: usize) -> Result<Option<usize>> {
|
||||||
|
Ok(Some(self.len(tree)?))
|
||||||
|
}
|
||||||
|
|
||||||
fn insert(&self, tree: usize, key: &[u8], value: &[u8]) -> Result<Option<Value>> {
|
fn insert(&self, tree: usize, key: &[u8], value: &[u8]) -> Result<Option<Value>> {
|
||||||
trace!("insert {}: lock db", tree);
|
trace!("insert {}: lock db", tree);
|
||||||
let this = self.0.lock().unwrap();
|
let this = self.0.lock().unwrap();
|
||||||
|
|
|
@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use garage_util::crdt::*;
|
use garage_util::crdt::*;
|
||||||
use garage_util::data::*;
|
use garage_util::data::*;
|
||||||
use garage_util::error::Error as GarageError;
|
use garage_util::error::Error as GarageError;
|
||||||
|
use garage_util::formater::format_table_to_string;
|
||||||
use garage_util::time::*;
|
use garage_util::time::*;
|
||||||
|
|
||||||
use garage_table::replication::*;
|
use garage_table::replication::*;
|
||||||
|
@ -808,6 +809,7 @@ impl AdminRpcHandler {
|
||||||
.unwrap_or_else(|| "(unknown)".into()),
|
.unwrap_or_else(|| "(unknown)".into()),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
writeln!(&mut ret, "\nDatabase engine: {}", self.garage.db.engine()).unwrap();
|
writeln!(&mut ret, "\nDatabase engine: {}", self.garage.db.engine()).unwrap();
|
||||||
|
|
||||||
// Gather ring statistics
|
// Gather ring statistics
|
||||||
|
@ -826,21 +828,38 @@ impl AdminRpcHandler {
|
||||||
writeln!(&mut ret, " {:?} {}", n, c).unwrap();
|
writeln!(&mut ret, " {:?} {}", n, c).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.gather_table_stats(&mut ret, &self.garage.bucket_table, &opt)?;
|
// Gather table statistics
|
||||||
self.gather_table_stats(&mut ret, &self.garage.key_table, &opt)?;
|
let mut table = vec![" Table\tItems\tMklItems\tMklTodo\tGcTodo".into()];
|
||||||
self.gather_table_stats(&mut ret, &self.garage.object_table, &opt)?;
|
table.push(self.gather_table_stats(&self.garage.bucket_table, opt.detailed)?);
|
||||||
self.gather_table_stats(&mut ret, &self.garage.version_table, &opt)?;
|
table.push(self.gather_table_stats(&self.garage.key_table, opt.detailed)?);
|
||||||
self.gather_table_stats(&mut ret, &self.garage.block_ref_table, &opt)?;
|
table.push(self.gather_table_stats(&self.garage.object_table, opt.detailed)?);
|
||||||
|
table.push(self.gather_table_stats(&self.garage.version_table, opt.detailed)?);
|
||||||
|
table.push(self.gather_table_stats(&self.garage.block_ref_table, opt.detailed)?);
|
||||||
|
write!(
|
||||||
|
&mut ret,
|
||||||
|
"\nTable stats:\n{}",
|
||||||
|
format_table_to_string(table)
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Gather block manager statistics
|
||||||
writeln!(&mut ret, "\nBlock manager stats:").unwrap();
|
writeln!(&mut ret, "\nBlock manager stats:").unwrap();
|
||||||
if opt.detailed {
|
let rc_len = if opt.detailed {
|
||||||
writeln!(
|
self.garage.block_manager.rc_len()?.to_string()
|
||||||
&mut ret,
|
} else {
|
||||||
" number of RC entries (~= number of blocks): {}",
|
self.garage
|
||||||
self.garage.block_manager.rc_len()?
|
.block_manager
|
||||||
)
|
.rc_fast_len()?
|
||||||
.unwrap();
|
.map(|x| x.to_string())
|
||||||
}
|
.unwrap_or_else(|| "NC".into())
|
||||||
|
};
|
||||||
|
|
||||||
|
writeln!(
|
||||||
|
&mut ret,
|
||||||
|
" number of RC entries (~= number of blocks): {}",
|
||||||
|
rc_len
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
writeln!(
|
writeln!(
|
||||||
&mut ret,
|
&mut ret,
|
||||||
" resync queue length: {}",
|
" resync queue length: {}",
|
||||||
|
@ -854,43 +873,50 @@ impl AdminRpcHandler {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
if !opt.detailed {
|
||||||
|
writeln!(&mut ret, "\nIf values are missing (marked as NC), consider adding the --detailed flag - this will be slow.").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_table_stats<F, R>(
|
fn gather_table_stats<F, R>(
|
||||||
&self,
|
&self,
|
||||||
to: &mut String,
|
|
||||||
t: &Arc<Table<F, R>>,
|
t: &Arc<Table<F, R>>,
|
||||||
opt: &StatsOpt,
|
detailed: bool,
|
||||||
) -> Result<(), Error>
|
) -> Result<String, Error>
|
||||||
where
|
where
|
||||||
F: TableSchema + 'static,
|
F: TableSchema + 'static,
|
||||||
R: TableReplication + 'static,
|
R: TableReplication + 'static,
|
||||||
{
|
{
|
||||||
writeln!(to, "\nTable stats for {}", F::TABLE_NAME).unwrap();
|
let (data_len, mkl_len) = if detailed {
|
||||||
if opt.detailed {
|
(
|
||||||
writeln!(
|
t.data.store.len().map_err(GarageError::from)?.to_string(),
|
||||||
to,
|
t.merkle_updater.merkle_tree_len()?.to_string(),
|
||||||
" number of items: {}",
|
|
||||||
t.data.store.len().map_err(GarageError::from)?
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
} else {
|
||||||
writeln!(
|
(
|
||||||
to,
|
t.data
|
||||||
" Merkle tree size: {}",
|
.store
|
||||||
t.merkle_updater.merkle_tree_len()?
|
.fast_len()
|
||||||
|
.map_err(GarageError::from)?
|
||||||
|
.map(|x| x.to_string())
|
||||||
|
.unwrap_or_else(|| "NC".into()),
|
||||||
|
t.merkle_updater
|
||||||
|
.merkle_tree_fast_len()?
|
||||||
|
.map(|x| x.to_string())
|
||||||
|
.unwrap_or_else(|| "NC".into()),
|
||||||
)
|
)
|
||||||
.unwrap();
|
};
|
||||||
}
|
|
||||||
writeln!(
|
|
||||||
to,
|
|
||||||
" Merkle updater todo queue length: {}",
|
|
||||||
t.merkle_updater.todo_len()?
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
writeln!(to, " GC todo queue length: {}", t.data.gc_todo_len()?).unwrap();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(format!(
|
||||||
|
" {}\t{}\t{}\t{}\t{}",
|
||||||
|
F::TABLE_NAME,
|
||||||
|
data_len,
|
||||||
|
mkl_len,
|
||||||
|
t.merkle_updater.todo_len()?,
|
||||||
|
t.data.gc_todo_len()?
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================ WORKER COMMANDS ====================
|
// ================ WORKER COMMANDS ====================
|
||||||
|
|
|
@ -293,6 +293,10 @@ where
|
||||||
Ok(self.data.merkle_tree.len()?)
|
Ok(self.data.merkle_tree.len()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn merkle_tree_fast_len(&self) -> Result<Option<usize>, Error> {
|
||||||
|
Ok(self.data.merkle_tree.fast_len()?)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn todo_len(&self) -> Result<usize, Error> {
|
pub fn todo_len(&self) -> Result<usize, Error> {
|
||||||
Ok(self.data.merkle_todo.len()?)
|
Ok(self.data.merkle_todo.len()?)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub fn format_table(data: Vec<String>) {
|
pub fn format_table_to_string(data: Vec<String>) -> String {
|
||||||
let data = data
|
let data = data
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.split('\t').collect::<Vec<_>>())
|
.map(|s| s.split('\t').collect::<Vec<_>>())
|
||||||
|
@ -24,5 +24,9 @@ pub fn format_table(data: Vec<String>) {
|
||||||
out.push('\n');
|
out.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
print!("{}", out);
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format_table(data: Vec<String>) {
|
||||||
|
print!("{}", format_table_to_string(data));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue