11use crate :: common:: format:: human_size;
22use crate :: dashboard:: data:: DashboardData ;
33use itertools:: Itertools ;
4- use ratatui:: layout:: { Constraint , Rect } ;
4+ use ratatui:: layout:: { Alignment , Constraint , Rect } ;
5+ use ratatui:: style:: Color ;
6+ use ratatui:: text:: { Line , Span } ;
57use ratatui:: widgets:: { Cell , Row , Table } ;
68use std:: cmp;
79use tako:: hwstats:: MemoryStats ;
@@ -11,7 +13,7 @@ use tako::resources::{
1113use tako:: worker:: WorkerConfiguration ;
1214use tako:: { Set , WorkerId } ;
1315
14- use crate :: dashboard:: ui:: styles:: { self , table_style_deselected} ;
16+ use crate :: dashboard:: ui:: styles:: { self , style_table_title , table_style_deselected} ;
1517use crate :: dashboard:: ui:: terminal:: DashboardFrame ;
1618use crate :: dashboard:: ui:: widgets:: progressbar:: {
1719 ProgressPrintStyle , get_cpu_progress_bar_color, render_progress_bar_at,
@@ -112,6 +114,28 @@ struct WorkerCpuState {
112114 assigned_cpus : Set < ResourceIndex > ,
113115}
114116
117+ impl WorkerCpuState {
118+ fn get_cpu_status ( & self , resource_idx : & ResourceIndex ) -> CpuStatus {
119+ if self . assigned_cpus . contains ( resource_idx) {
120+ CpuStatus :: Assigned
121+ } else if self . managed_cpus . contains ( resource_idx) {
122+ CpuStatus :: Managed
123+ } else {
124+ CpuStatus :: Other
125+ }
126+ }
127+ }
128+
129+ #[ derive( PartialEq , PartialOrd , Eq , Ord , Clone , Copy ) ]
130+ pub enum CpuStatus {
131+ // Cpu is managed by this worker, and is assigned to atleast one task
132+ Assigned ,
133+ // Cpu is managed by this worker
134+ Managed ,
135+ // Cpu is seen by HQ but not managed by this worker
136+ Other ,
137+ }
138+
115139impl CpuUtilTable {
116140 pub fn update (
117141 & mut self ,
@@ -136,27 +160,24 @@ impl CpuUtilTable {
136160 . workers ( )
137161 . query_worker_overview_at ( worker_id, data. current_time ( ) )
138162 {
139- let assigned_cpus: Set < ResourceIndex > = match self . cpu_view_mode {
140- CpuViewMode :: WorkerManaged | CpuViewMode :: WorkerAssigned => overview
141- . item
142- . running_tasks
143- . iter ( )
144- . flat_map ( |( _id, task_resource_alloc) | {
145- task_resource_alloc
146- . resources
147- . iter ( )
148- . filter_map ( |resource_alloc| {
149- if resource_alloc. resource == CPU_RESOURCE_NAME {
150- Some ( resource_alloc. indices . iter ( ) . map ( |( index, _) | * index) )
151- } else {
152- None
153- }
154- } )
155- } )
156- . flatten ( )
157- . collect ( ) ,
158- CpuViewMode :: Global => Set :: default ( ) ,
159- } ;
163+ let assigned_cpus: Set < ResourceIndex > = overview
164+ . item
165+ . running_tasks
166+ . iter ( )
167+ . flat_map ( |( _id, task_resource_alloc) | {
168+ task_resource_alloc
169+ . resources
170+ . iter ( )
171+ . filter_map ( |resource_alloc| {
172+ if resource_alloc. resource == CPU_RESOURCE_NAME {
173+ Some ( resource_alloc. indices . iter ( ) . map ( |( index, _) | * index) )
174+ } else {
175+ None
176+ }
177+ } )
178+ } )
179+ . flatten ( )
180+ . collect ( ) ;
160181
161182 self . cpu_state = Some ( WorkerCpuState {
162183 managed_cpus,
@@ -193,18 +214,18 @@ impl CpuUtilTable {
193214 . cpu_view_mode
194215 . get_visible_indices ( util. cpu . len ( ) , cpu_state) ;
195216
196- let cell_data: Vec < ( u32 , f64 , bool ) > = visible_indices
217+ let cell_data: Vec < ( u32 , f64 , CpuStatus ) > = visible_indices
197218 . into_iter ( )
198219 . map ( |idx| {
199220 let val = util
200221 . cpu
201222 . get ( idx. as_num ( ) as usize )
202223 . copied ( )
203224 . unwrap_or_default ( ) ;
204- let is_used = cpu_state. assigned_cpus . contains ( & idx) ;
205- ( idx. as_num ( ) , val, is_used )
225+ let status = cpu_state. get_cpu_status ( & idx) ;
226+ ( idx. as_num ( ) , val, status )
206227 } )
207- . sorted_by_key ( |& ( idx, _, used ) | ( std :: cmp :: Reverse ( used ) , idx) )
228+ . sorted_by_key ( |& ( idx, _, status ) | ( status , idx) )
208229 . collect ( ) ;
209230
210231 let constraints = get_column_constraints ( rect, cell_data. len ( ) ) ;
@@ -221,13 +242,9 @@ impl CpuUtilTable {
221242 . iter ( )
222243 . skip ( row_start_idx)
223244 . step_by ( num_rows)
224- . map ( |( id, cpu_util, used ) | {
245+ . map ( |( id, cpu_util, status ) | {
225246 let progress = cpu_util / 100.0 ;
226- let style = get_cpu_progress_bar_color (
227- progress,
228- * used,
229- & self . cpu_view_mode ,
230- ) ;
247+ let style = get_cpu_progress_bar_color ( progress, status) ;
231248
232249 Cell :: from ( render_progress_bar_at (
233250 Some ( format ! ( "{id:>3} " ) ) ,
@@ -259,7 +276,9 @@ impl CpuUtilTable {
259276 human_size( mem_used) ,
260277 human_size( util. memory. total)
261278 ) ) ;
262- let body_block = styles:: table_block_with_title ( title) ;
279+
280+ let legend = create_legend ( & self . cpu_view_mode ) ;
281+ let body_block = styles:: table_block_with_title ( title) . title_bottom ( legend) ;
263282
264283 let table = Table :: new ( rows, constraints)
265284 . block ( body_block)
@@ -324,7 +343,7 @@ fn get_column_constraints(rect: Rect, num_cpus: usize) -> Vec<Constraint> {
324343
325344fn create_title_info (
326345 util_render_mode : & CpuViewMode ,
327- cpu_table_data : & [ ( u32 , f64 , bool ) ] ,
346+ cpu_table_data : & [ ( u32 , f64 , CpuStatus ) ] ,
328347) -> ( String , usize , f64 ) {
329348 let which_util = match util_render_mode {
330349 CpuViewMode :: Global => "Node" ,
@@ -368,3 +387,32 @@ fn cpu_resource_desc_to_idx(resource: &ResourceDescriptorItem) -> Option<Set<Res
368387 ResourceDescriptorKind :: Sum { .. } => unreachable ! ( ) ,
369388 }
370389}
390+
391+ fn create_legend < ' a > ( view_mode : & ' a CpuViewMode ) -> Line < ' a > {
392+ let title_style = style_table_title ( ) ;
393+
394+ let mut legend_info = vec ! [
395+ Span :: styled( "[" , title_style) ,
396+ Span :: styled( "■" , title_style. fg( Color :: Green ) ) ,
397+ Span :: styled( "/" , title_style) ,
398+ Span :: styled( "■" , title_style. fg( Color :: Yellow ) ) ,
399+ Span :: styled( "/" , title_style) ,
400+ Span :: styled( "■" , title_style. fg( Color :: Red ) ) ,
401+ Span :: styled( " Assigned" , title_style) ,
402+ ] ;
403+
404+ if * view_mode == CpuViewMode :: WorkerManaged || * view_mode == CpuViewMode :: Global {
405+ legend_info. push ( Span :: styled ( " | " , title_style) ) ;
406+ legend_info. push ( Span :: styled ( "■ " , title_style. fg ( Color :: LightBlue ) ) ) ;
407+ legend_info. push ( Span :: styled ( "Managed" , style_table_title ( ) ) ) ;
408+ }
409+ if * view_mode == CpuViewMode :: Global {
410+ legend_info. push ( Span :: styled ( " | " , title_style) ) ;
411+ legend_info. push ( Span :: styled ( "■ " , title_style. fg ( Color :: Magenta ) ) ) ;
412+ legend_info. push ( Span :: styled ( "Other" , title_style) ) ;
413+ }
414+
415+ legend_info. push ( Span :: styled ( "]" , title_style) ) ;
416+
417+ Line :: from ( legend_info) . alignment ( Alignment :: Right )
418+ }
0 commit comments