use ckb_db::internal::ops::{GetColumnFamilys, GetProperty, GetPropertyCF};
#[derive(Debug, Clone)]
enum PropertyValue<T> {
Value(T),
Null,
Error(String),
}
impl PropertyValue<u64> {
pub(crate) fn as_i64(&self) -> i64 {
match self {
Self::Value(v) => *v as i64,
Self::Null => -1,
Self::Error(_) => -2,
}
}
}
impl<T> From<Result<Option<T>, String>> for PropertyValue<T> {
fn from(res: Result<Option<T>, String>) -> Self {
match res {
Ok(Some(v)) => Self::Value(v),
Ok(None) => Self::Null,
Err(e) => Self::Error(e),
}
}
}
pub trait TrackRocksDBMemory {
fn gather_memory_stats(&self) {
self.gather_int_values("estimate-table-readers-mem");
self.gather_int_values("size-all-mem-tables");
self.gather_int_values("cur-size-all-mem-tables");
self.gather_int_values("block-cache-capacity");
self.gather_int_values("block-cache-usage");
self.gather_int_values("block-cache-pinned-usage");
}
fn gather_int_values(&self, _: &str) {}
}
pub(crate) struct DummyRocksDB;
impl TrackRocksDBMemory for DummyRocksDB {}
impl<RocksDB> TrackRocksDBMemory for RocksDB
where
RocksDB: GetColumnFamilys + GetProperty + GetPropertyCF,
{
fn gather_int_values(&self, key: &str) {
let mut values = Vec::new();
for (cf_name, cf) in self.get_cfs() {
let value_col: PropertyValue<u64> = self
.property_int_value_cf(cf, &format!("rocksdb.{key}"))
.map_err(|err| format!("{err}"))
.into();
if let Some(metrics) = ckb_metrics::handle() {
metrics
.ckb_sys_mem_rocksdb
.with_label_values(&[key, cf_name])
.set(value_col.as_i64());
}
values.push(value_col);
}
}
}