summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--below/model/src/lib.rs2
-rw-r--r--below/render/src/default_configs.rs20
-rw-r--r--below/view/src/default_styles.rs2
-rw-r--r--below/view/src/lib.rs4
-rw-r--r--below/view/src/render.rs9
-rw-r--r--below/view/src/summary_view.rs62
-rw-r--r--below/view/src/viewrc.rs14
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 {