diff --git a/agent/src/collectors/service.rs b/agent/src/collectors/service.rs index 3db4982..0cc217d 100644 --- a/agent/src/collectors/service.rs +++ b/agent/src/collectors/service.rs @@ -538,26 +538,10 @@ impl ServiceCollector { cache.get(service).cloned() } - async fn should_update_description(&self, service: &str) -> bool { - // Simple time-based throttling - only run expensive descriptions every ~30 seconds - // Use a hash of the current time to spread out when different services get described - let now = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_secs(); - - let service_hash = service.as_bytes().iter().fold(0u64, |acc, &b| { - acc.wrapping_mul(31).wrapping_add(b as u64) - }); - - // Each service gets its description updated every 30 seconds, but staggered - let update_interval = 30; // seconds - let service_offset = service_hash % update_interval; - - let should_update = (now + service_offset) % update_interval == 0; - - - should_update + async fn should_update_description(&self, _service: &str) -> bool { + // For now, always update descriptions since we have caching + // The cache will prevent redundant work + true } async fn get_service_description(&self, service: &str) -> Option> { diff --git a/dashboard/src/ui/system.rs b/dashboard/src/ui/system.rs index 842d64a..1af22e7 100644 --- a/dashboard/src/ui/system.rs +++ b/dashboard/src/ui/system.rs @@ -84,21 +84,79 @@ fn render_metrics( // CPU dataset let cpu_status = status_level_from_color(cpu_icon_color); let mut cpu_dataset = WidgetDataSet::new(vec!["CPU load".to_string(), "CPU temp".to_string()], Some(WidgetStatus::new(cpu_status))); - - // Get C-state descriptions - let cstate_descriptions = summary.cpu_cstate.as_ref() - .map(|states| states.clone()) - .unwrap_or_else(|| vec!["No C-state data".to_string()]); - cpu_dataset.add_row( Some(WidgetStatus::new(cpu_status)), - cstate_descriptions, + vec![], vec![ format!("{:.2} • {:.2} • {:.2}", summary.cpu_load_1, summary.cpu_load_5, summary.cpu_load_15), format_optional_metric(summary.cpu_temp_c, "°C"), ], ); + // C-state dataset - all C-states as columns in one row, ordered properly + let mut cstate_headers = Vec::new(); + let mut cstate_values = Vec::new(); + + if let Some(cstates) = summary.cpu_cstate.as_ref() { + // Parse all C-states first + let mut parsed_cstates: Vec<(String, String)> = Vec::new(); + for cstate_info in cstates { + if let Some((state, percent)) = cstate_info.split_once(": ") { + parsed_cstates.push((state.to_string(), percent.to_string())); + } + } + + // Sort by C-state order: POLL, C1, C1E, C3, C6, C7s, C8, C9, C10 + parsed_cstates.sort_by(|a, b| { + let order_a = match a.0.as_str() { + "POLL" => 0, + "C1" => 1, + "C1E" => 2, + "C3" => 3, + "C6" => 4, + "C7s" => 5, + "C8" => 6, + "C9" => 7, + "C10" => 8, + _ => 99, + }; + let order_b = match b.0.as_str() { + "POLL" => 0, + "C1" => 1, + "C1E" => 2, + "C3" => 3, + "C6" => 4, + "C7s" => 5, + "C8" => 6, + "C9" => 7, + "C10" => 8, + _ => 99, + }; + order_a.cmp(&order_b) + }); + + // Take all available C-states (or limit to fit display) + for (state, percent) in parsed_cstates.into_iter().take(8) { + cstate_headers.push(state); + cstate_values.push(percent); + } + } + + let mut cstate_dataset = WidgetDataSet::new(cstate_headers, Some(WidgetStatus::new(StatusLevel::Ok))); + if !cstate_values.is_empty() { + cstate_dataset.add_row( + Some(WidgetStatus::new(StatusLevel::Ok)), + vec![], + cstate_values, + ); + } else { + cstate_dataset.add_row( + Some(WidgetStatus::new(StatusLevel::Unknown)), + vec![], + vec!["No data".to_string()], + ); + } + // GPU dataset let gpu_status = status_level_from_color(gpu_icon_color); let mut gpu_dataset = WidgetDataSet::new(vec!["GPU load".to_string(), "GPU temp".to_string()], Some(WidgetStatus::new(gpu_status))); @@ -125,8 +183,8 @@ fn render_metrics( }; let overall_status = Some(WidgetStatus::new(overall_status_level)); - // Render all three datasets in a single combined widget - render_combined_widget_data(frame, area, "System".to_string(), overall_status, vec![memory_dataset, cpu_dataset, gpu_dataset]); + // Render all datasets in a single combined widget + render_combined_widget_data(frame, area, "System".to_string(), overall_status, vec![memory_dataset, cpu_dataset, cstate_dataset, gpu_dataset]); } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]