Skip to content

Commit 68942d2

Browse files
committed
add tui resource usage view
1 parent 0580980 commit 68942d2

16 files changed

Lines changed: 720 additions & 22 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coman/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "coman"
3-
version = "0.7.0"
3+
version = "0.8.0"
44
edition = "2024"
55
description = "Compute Manager for managing HPC compute"
66
authors = ["Ralf Grubenmann <ralf.grubenmann@sdsc.ethz.ch>"]

coman/src/app/ids.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub enum Id {
55
WorkloadList,
66
WorkloadLogs,
77
WorkloadDetails,
8+
WorkloadResourceUsage,
89
GlobalListener,
910
Menu,
1011
InfoPopup,

coman/src/app/messages.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub enum CscsMsg {
5353
#[derive(Debug, PartialEq)]
5454
pub enum JobMsg {
5555
Log(usize),
56+
ResourceUsage(usize),
5657
Details(JobDetail),
5758
GetDetails(usize),
5859
Cancel(usize),

coman/src/app/model.rs

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ use crate::{
2121
},
2222
components::{
2323
context_menu::ContextMenu, download_popup::DownloadTargetInput, error_popup::ErrorPopup, info_popup::InfoPopup,
24-
login_popup::LoginPopup, system_select_popup::SystemSelectPopup, workload_details::WorkloadDetails,
25-
workload_list::WorkloadList, workload_log::WorkloadLog,
24+
login_popup::LoginPopup, resource_usage::ResourceUsage, system_select_popup::SystemSelectPopup,
25+
workload_details::WorkloadDetails, workload_list::WorkloadList, workload_log::WorkloadLog,
2626
},
2727
cscs::{
2828
handlers::{cscs_login, cscs_system_set},
29-
ports::{BackgroundTask, JobLogAction},
29+
ports::{BackgroundTask, JobLogAction, JobResourceUsageAction},
3030
},
3131
trace_dbg,
3232
util::ui::{draw_area_in_absolute, draw_area_in_absolute_fixed_height},
@@ -58,6 +58,10 @@ where
5858
/// sending None stops watching
5959
pub job_log_tx: mpsc::Sender<JobLogAction>,
6060

61+
/// Triggers watching job logs
62+
/// sending None stops watching
63+
pub job_resource_usage_tx: mpsc::Sender<JobResourceUsageAction>,
64+
6165
/// Allows creating user events based on messages
6266
pub user_event_tx: mpsc::Sender<UserEvent>,
6367

@@ -69,12 +73,14 @@ impl<T> Model<T>
6973
where
7074
T: TerminalAdapter,
7175
{
76+
#[allow(clippy::too_many_arguments)]
7277
pub fn new(
7378
app: Application<Id, Msg, UserEvent>,
7479
bridge: TerminalBridge<T>,
7580
error_tx: mpsc::Sender<String>,
7681
select_system_tx: mpsc::Sender<()>,
7782
job_log_tx: mpsc::Sender<JobLogAction>,
83+
job_resource_usage_tx: mpsc::Sender<JobResourceUsageAction>,
7884
user_event_tx: mpsc::Sender<UserEvent>,
7985
background_task_tx: mpsc::Sender<BackgroundTask>,
8086
) -> Self {
@@ -87,6 +93,7 @@ where
8793
error_tx,
8894
select_system_tx,
8995
job_log_tx,
96+
job_resource_usage_tx,
9097
user_event_tx,
9198
background_task_tx,
9299
}
@@ -151,6 +158,7 @@ where
151158
app.view(&Id::WorkloadList, frame, area);
152159
app.view(&Id::WorkloadLogs, frame, area);
153160
app.view(&Id::WorkloadDetails, frame, area);
161+
app.view(&Id::WorkloadResourceUsage, frame, area);
154162
}
155163
fn view_files(app: &mut Application<Id, Msg, UserEvent>, frame: &mut Frame, area: Rect) {
156164
if app.mounted(&Id::FileView) {
@@ -314,6 +322,9 @@ where
314322
if self.app.mounted(&Id::WorkloadDetails) {
315323
assert!(self.app.umount(&Id::WorkloadDetails).is_ok());
316324
}
325+
if self.app.mounted(&Id::WorkloadResourceUsage) {
326+
assert!(self.app.umount(&Id::WorkloadResourceUsage).is_ok());
327+
}
317328
if !self.app.mounted(&Id::WorkloadLogs) {
318329
assert!(
319330
self.app
@@ -362,6 +373,12 @@ where
362373
.is_ok()
363374
);
364375
}
376+
if self.app.mounted(&Id::WorkloadResourceUsage) {
377+
assert!(self.app.umount(&Id::WorkloadResourceUsage).is_ok());
378+
}
379+
if self.app.mounted(&Id::WorkloadLogs) {
380+
assert!(self.app.umount(&Id::WorkloadLogs).is_ok());
381+
}
365382
if !self.app.mounted(&Id::WorkloadDetails) {
366383
assert!(
367384
self.app
@@ -372,6 +389,37 @@ where
372389
assert!(self.app.active(&Id::WorkloadDetails).is_ok());
373390
None
374391
}
392+
JobMsg::ResourceUsage(jobid) => {
393+
if self.app.mounted(&Id::WorkloadList) {
394+
assert!(
395+
self.app
396+
.attr(&Id::WorkloadList, Attribute::Display, AttrValue::Flag(false))
397+
.is_ok()
398+
);
399+
}
400+
if self.app.mounted(&Id::WorkloadDetails) {
401+
assert!(self.app.umount(&Id::WorkloadDetails).is_ok());
402+
}
403+
if self.app.mounted(&Id::WorkloadLogs) {
404+
assert!(self.app.umount(&Id::WorkloadLogs).is_ok());
405+
}
406+
if !self.app.mounted(&Id::WorkloadResourceUsage) {
407+
assert!(
408+
self.app
409+
.mount(Id::WorkloadResourceUsage, Box::new(ResourceUsage::default()), vec![])
410+
.is_ok()
411+
);
412+
}
413+
assert!(self.app.active(&Id::WorkloadResourceUsage).is_ok());
414+
let job_resource_usage_tx = self.job_resource_usage_tx.clone();
415+
tokio::spawn(async move {
416+
job_resource_usage_tx
417+
.send(JobResourceUsageAction::Job(jobid))
418+
.await
419+
.unwrap();
420+
});
421+
None
422+
}
375423
JobMsg::Switch => {
376424
let job_log_tx = self.job_log_tx.clone();
377425
tokio::spawn(async move {
@@ -386,6 +434,9 @@ where
386434
if self.app.mounted(&Id::WorkloadDetails) {
387435
assert!(self.app.umount(&Id::WorkloadDetails).is_ok());
388436
}
437+
if self.app.mounted(&Id::WorkloadResourceUsage) {
438+
assert!(self.app.umount(&Id::WorkloadResourceUsage).is_ok());
439+
}
389440
if !self.app.mounted(&Id::WorkloadList) {
390441
assert!(
391442
self.app
@@ -404,6 +455,11 @@ where
404455
// stopp polling for logs
405456
job_log_tx.send(JobLogAction::Stop).await.unwrap();
406457
});
458+
let job_resource_usage_tx = self.job_resource_usage_tx.clone();
459+
tokio::spawn(async move {
460+
// stopp polling for resource_usages
461+
job_resource_usage_tx.send(JobResourceUsageAction::Stop).await.unwrap();
462+
});
407463
None
408464
}
409465
}

coman/src/app/user_events.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::{
22
app::messages::View,
3+
cli::rpc::ResourceUsage,
34
cscs::api_client::types::{Job, JobDetail, PathEntry, System},
45
};
56

@@ -9,6 +10,7 @@ pub enum CscsEvent {
910
GotWorkloadData(Vec<Job>),
1011
GotJobLog(String),
1112
GotJobDetails(JobDetail),
13+
GotJobResourceUsage(ResourceUsage),
1214
SelectSystemList(Vec<System>),
1315
SystemSelected(String),
1416
}

coman/src/cli/exec.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use pid1::Pid1Settings;
1111
use rust_supervisor::{ChildType, Supervisor, SupervisorConfig};
1212
use tokio::{io::AsyncWriteExt, net::TcpStream};
1313

14-
use crate::cli::rpc::RpcHandler;
14+
use crate::cli::rpc::{COMAN_RPC_ALPN, RpcHandler};
1515

1616
const SECRET_KEY_ENV: &str = "COMAN_IROH_SECRET";
1717
const PORT_FORWARD_ENV: &str = "COMAN_FORWARDED_PORTS";
@@ -126,7 +126,7 @@ async fn port_forward() -> Result<()> {
126126

127127
// add rpc server
128128
let rpc_handler = RpcHandler;
129-
builder = builder.accept(b"/coman/rpc", rpc_handler);
129+
builder = builder.accept(COMAN_RPC_ALPN, rpc_handler);
130130
let _router = builder.spawn();
131131
println!("port forwarding started");
132132

coman/src/cli/rpc.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,32 @@ use tokio_duplex::Duplex;
1111

1212
use crate::cli::app::COMAN_VERSION;
1313

14-
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
14+
pub const COMAN_RPC_ALPN: &[u8; 10] = b"/coman/rpc";
15+
16+
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
1517
pub struct ResourceUsage {
1618
pub cpu: f32,
1719
pub rss: u64,
18-
pub vss: u64,
20+
pub vsz: u64,
1921
pub gpu: Option<Vec<(u64, u64)>>,
2022
}
2123

24+
impl Eq for ResourceUsage {}
25+
impl Ord for ResourceUsage {
26+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
27+
self.cpu.total_cmp(&other.cpu).then(
28+
self.rss
29+
.cmp(&other.rss)
30+
.then(self.vsz.cmp(&other.vsz).then(self.gpu.cmp(&other.gpu))),
31+
)
32+
}
33+
}
34+
impl PartialOrd for ResourceUsage {
35+
fn partial_cmp(&self, other: &ResourceUsage) -> Option<std::cmp::Ordering> {
36+
Some(self.cmp(other))
37+
}
38+
}
39+
2240
#[tarpc::service]
2341
pub trait ComanRPC {
2442
async fn version() -> String;
@@ -70,7 +88,7 @@ impl ComanRPC for RpcServer {
7088
ResourceUsage {
7189
cpu: process.cpu_usage() / sys.cpus().len() as f32,
7290
rss: process.memory(),
73-
vss: process.virtual_memory(),
91+
vsz: process.virtual_memory(),
7492
gpu: gpu_usage,
7593
}
7694
}

coman/src/components/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub(crate) mod file_tree;
55
pub(crate) mod global_listener;
66
pub(crate) mod info_popup;
77
pub(crate) mod login_popup;
8+
pub(crate) mod resource_usage;
89
pub(crate) mod status_bar;
910
pub(crate) mod system_select_popup;
1011
pub(crate) mod toolbar;

0 commit comments

Comments
 (0)