diff options
-rw-r--r-- | below/model/src/lib.rs | 2 | ||||
-rw-r--r-- | below/render/src/default_configs.rs | 20 | ||||
-rw-r--r-- | below/view/src/default_styles.rs | 2 | ||||
-rw-r--r-- | below/view/src/lib.rs | 4 | ||||
-rw-r--r-- | below/view/src/render.rs | 9 | ||||
-rw-r--r-- | below/view/src/summary_view.rs | 62 | ||||
-rw-r--r-- | below/view/src/viewrc.rs | 14 |
7 files changed, 112 insertions, 1 deletions
diff --git a/below/model/src/lib.rs b/below/model/src/lib.rs index 307ccf01..c2e5b067 100644 --- a/below/model/src/lib.rs +++ b/below/model/src/lib.rs @@ -470,7 +470,7 @@ pub struct NetworkStats<'a> { ethtool: &'a Option<ethtool::EthtoolStats>, } -#[derive(Serialize, Deserialize, below_derive::Queriable)] +#[derive(Clone, Serialize, Deserialize, below_derive::Queriable)] pub struct Model { #[queriable(ignore)] pub time_elapsed: Duration, diff --git a/below/render/src/default_configs.rs b/below/render/src/default_configs.rs index 016f3cae..7d8e5080 100644 --- a/below/render/src/default_configs.rs +++ b/below/render/src/default_configs.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use model::ProcessModelFieldId; use model::SingleCgroupModelFieldId; use model::SingleProcessModelFieldId; use RenderFormat::Duration; @@ -24,6 +25,25 @@ use RenderFormat::SectorReadableSize; use super::*; +impl HasRenderConfig for model::Model { + fn get_render_config_builder(field_id: &Self::FieldId) -> RenderConfigBuilder { + use model::ModelFieldId::*; + let rc = RenderConfigBuilder::new(); + match field_id { + System(field_id) => model::SystemModel::get_render_config_builder(field_id), + Cgroup(field_id) => { + model::SingleCgroupModel::get_render_config_builder(&field_id.subquery_id.0) + } + Process(ProcessModelFieldId::Processes(field_id)) => { + model::SingleProcessModel::get_render_config_builder(&field_id.subquery_id.0) + } + Network(field_id) => model::NetworkModel::get_render_config_builder(field_id), + Gpu(_) => rc, + Resctrl(_) => rc, + } + } +} + impl HasRenderConfig for model::SingleCgroupModel { fn get_render_config_builder(field_id: &Self::FieldId) -> RenderConfigBuilder { use model::SingleCgroupModelFieldId::*; diff --git a/below/view/src/default_styles.rs b/below/view/src/default_styles.rs index bdb17e92..4e46bde7 100644 --- a/below/view/src/default_styles.rs +++ b/below/view/src/default_styles.rs @@ -92,6 +92,8 @@ impl HasViewStyle for model::MemoryModel { } } +impl HasViewStyle for model::Model {} + impl HasViewStyle for model::SingleCpuModel {} impl HasViewStyle for model::VmModel {} diff --git a/below/view/src/lib.rs b/below/view/src/lib.rs index 6b456148..315ea8cf 100644 --- a/below/view/src/lib.rs +++ b/below/view/src/lib.rs @@ -240,6 +240,8 @@ pub struct ViewState { /// can certainly go higher (b/c of a loaded system or other delays). pub lowest_time_elapsed: Duration, pub timestamp: SystemTime, + // TODO: Replace other fields with model + pub model: Rc<RefCell<Model>>, pub system: Rc<RefCell<SystemModel>>, pub cgroup: Rc<RefCell<CgroupModel>>, pub process: Rc<RefCell<ProcessModel>>, @@ -262,6 +264,7 @@ impl ViewState { self.lowest_time_elapsed = model.time_elapsed; } self.timestamp = model.timestamp; + self.model.replace(model.clone()); self.system.replace(model.system); self.cgroup.replace(model.cgroup); self.process.replace(model.process); @@ -281,6 +284,7 @@ impl ViewState { time_elapsed: model.time_elapsed, lowest_time_elapsed: model.time_elapsed, timestamp: model.timestamp, + model: Rc::new(RefCell::new(model.clone())), system: Rc::new(RefCell::new(model.system)), cgroup: Rc::new(RefCell::new(model.cgroup)), process: Rc::new(RefCell::new(model.process)), diff --git a/below/view/src/render.rs b/below/view/src/render.rs index 4ffccae8..13e74c73 100644 --- a/below/view/src/render.rs +++ b/below/view/src/render.rs @@ -87,6 +87,11 @@ impl ViewConfig { self.apply_style(rendered, field) } + pub fn render_tight(&self, field: Option<Field>) -> StyledString { + let rendered = self.render_config.render(field.clone(), false); + self.apply_style(rendered, field) + } + pub fn render_indented(&self, field: Option<Field>, depth: usize) -> StyledString { let rendered = self .render_config @@ -138,6 +143,10 @@ impl<F: FieldId> ViewItem<F> { pub fn render(&self, model: &F::Queriable) -> StyledString { self.config.render(model.query(&self.field_id)) } + + pub fn render_tight(&self, model: &F::Queriable) -> StyledString { + self.config.render_tight(model.query(&self.field_id)) + } } impl<F, T> ViewItem<F> diff --git a/below/view/src/summary_view.rs b/below/view/src/summary_view.rs index 76977b40..c884bda9 100644 --- a/below/view/src/summary_view.rs +++ b/below/view/src/summary_view.rs @@ -21,9 +21,13 @@ use crate::ViewState; mod render_impl { use std::collections::BTreeMap; + use std::str::FromStr; + use base_render::RenderConfig; use base_render::RenderConfigBuilder as Rc; use cursive::utils::markup::StyledString; + use model::Model; + use model::ModelFieldId; use model::Queriable; use model::SingleDiskModel; use model::SingleNetModel; @@ -31,6 +35,7 @@ mod render_impl { use once_cell::sync::Lazy; use crate::render::ViewItem; + use crate::viewrc::ViewRc; /// Renders corresponding Fields From SystemModel. type SummaryViewItem = ViewItem<model::SystemModelFieldId>; @@ -101,6 +106,21 @@ mod render_impl { row } + pub fn render_extra_row(extra_row: &SummaryViewExtraRow, model: &Model) -> StyledString { + let mut row = StyledString::new(); + if let Some(title) = &extra_row.title { + row.append(title.clone()); + } + for item in &extra_row.items { + if !row.is_empty() { + row.append(" | "); + } + row.append(format!("{} ", item.config.render_config.get_title())); + row.append(item.render_tight(model)); + } + row + } + pub fn render_read_write_models_row<'a, T: 'a + Queriable>( name: &'static str, models: impl Iterator<Item = (&'a String, &'a T)>, @@ -162,6 +182,39 @@ mod render_impl { ViewItem::from_default(TxBytesPerSec), ) } + + pub struct SummaryViewExtraRow { + pub title: Option<String>, + pub items: Vec<ViewItem<model::ModelFieldId>>, + } + + pub fn get_summary_view_extra_rows(viewrc: &ViewRc) -> Vec<SummaryViewExtraRow> { + if let Some(viewrc_rows) = viewrc.summary_view_extra_rows.as_ref() { + viewrc_rows + .iter() + .map(|viewrc_row| SummaryViewExtraRow { + title: viewrc_row.title.clone(), + items: viewrc_row + .items + .iter() + // Skip invalid field ids + .filter_map(|item| { + ModelFieldId::from_str(&item.field_id) + .map(|field_id| { + ViewItem::from_default(field_id).update(RenderConfig { + title: item.alias.clone(), + ..Default::default() + }) + }) + .ok() + }) + .collect(), + }) + .collect() + } else { + vec![] + } + } } fn fill_content(c: &mut Cursive, v: &mut LinearLayout) { @@ -184,6 +237,15 @@ fn fill_content(c: &mut Cursive, v: &mut LinearLayout) { view.add_child(TextView::new(io_row)); view.add_child(TextView::new(iface_row)); + let model = view_state.model.borrow(); + // TODO: Save the parsed extra rows in a struct and reuse + let extra_rows = render_impl::get_summary_view_extra_rows(&view_state.viewrc); + for extra_row in extra_rows { + view.add_child(TextView::new(render_impl::render_extra_row( + &extra_row, &model, + ))); + } + *v = view; } diff --git a/below/view/src/viewrc.rs b/below/view/src/viewrc.rs index 356eb105..267da630 100644 --- a/below/view/src/viewrc.rs +++ b/below/view/src/viewrc.rs @@ -28,6 +28,18 @@ pub enum DefaultFrontView { System, } +#[derive(Default, Deserialize)] +pub struct SummaryViewExtraRowItem { + pub alias: Option<String>, + pub field_id: String, +} + +#[derive(Default, Deserialize)] +pub struct SummaryViewExtraRow { + pub title: Option<String>, + pub items: Vec<SummaryViewExtraRowItem>, +} + /// Runtime configuration on the below view. #[derive(Default, Deserialize)] pub struct ViewRc { @@ -39,6 +51,8 @@ pub struct ViewRc { pub collapse_cgroups: Option<bool>, // Overrides cgroup name column width. pub cgroup_name_width: Option<usize>, + // Extra rows to add in the summary view. + pub summary_view_extra_rows: Option<Vec<SummaryViewExtraRow>>, } impl ViewRc { |