feat: simplify system metrics collection and improve status panel
- Removed unused token parameters from get_system_metrics function - Simplified metrics collection in BotOrchestrator by removing initial token check - Improved StatusPanel by: - Removing 1-second update throttle - Refreshing CPU usage more efficiently - Separating metrics collection from rendering - Using direct CPU measurement from sysinfo - Cleaned up unused imports and improved code organization The changes make the system monitoring more straightforward and efficient while maintaining all functionality.
This commit is contained in:
parent
b8ba0a7d41
commit
6a31e65842
4 changed files with 43 additions and 29 deletions
|
|
@ -5,7 +5,7 @@ use crate::shared::state::AppState;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use cron::Schedule;
|
use cron::Schedule;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use log::{error, trace};
|
use log::{error};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::time::{interval, Duration};
|
use tokio::time::{interval, Duration};
|
||||||
|
|
|
||||||
|
|
@ -423,8 +423,6 @@ impl BotOrchestrator {
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.parse::<usize>()
|
.parse::<usize>()
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
if let Ok(_metrics) = get_system_metrics(initial_tokens, max_context_size) {
|
|
||||||
}
|
|
||||||
let model = config_manager
|
let model = config_manager
|
||||||
.get_config(
|
.get_config(
|
||||||
&Uuid::parse_str(&message.bot_id).unwrap_or_default(),
|
&Uuid::parse_str(&message.bot_id).unwrap_or_default(),
|
||||||
|
|
@ -466,7 +464,7 @@ impl BotOrchestrator {
|
||||||
if last_progress_update.elapsed() >= progress_interval {
|
if last_progress_update.elapsed() >= progress_interval {
|
||||||
let current_tokens =
|
let current_tokens =
|
||||||
initial_tokens + crate::shared::utils::estimate_token_count(&full_response);
|
initial_tokens + crate::shared::utils::estimate_token_count(&full_response);
|
||||||
if let Ok(metrics) = get_system_metrics(current_tokens, max_context_size) {
|
if let Ok(metrics) = get_system_metrics() {
|
||||||
let _gpu_bar =
|
let _gpu_bar =
|
||||||
"█".repeat((metrics.gpu_usage.unwrap_or(0.0) / 5.0).round() as usize);
|
"█".repeat((metrics.gpu_usage.unwrap_or(0.0) / 5.0).round() as usize);
|
||||||
let _cpu_bar = "█".repeat((metrics.cpu_usage / 5.0).round() as usize);
|
let _cpu_bar = "█".repeat((metrics.cpu_usage / 5.0).round() as usize);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ pub struct SystemMetrics {
|
||||||
pub gpu_usage: Option<f32>,
|
pub gpu_usage: Option<f32>,
|
||||||
pub cpu_usage: f32,
|
pub cpu_usage: f32,
|
||||||
}
|
}
|
||||||
pub fn get_system_metrics(_current_tokens: usize, _max_tokens: usize) -> Result<SystemMetrics> {
|
pub fn get_system_metrics() -> Result<SystemMetrics> {
|
||||||
let mut sys = System::new();
|
let mut sys = System::new();
|
||||||
sys.refresh_cpu_usage();
|
sys.refresh_cpu_usage();
|
||||||
let cpu_usage = sys.global_cpu_usage();
|
let cpu_usage = sys.global_cpu_usage();
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,18 @@ use crate::config::ConfigManager;
|
||||||
use crate::nvidia;
|
use crate::nvidia;
|
||||||
use crate::shared::models::schema::bots::dsl::*;
|
use crate::shared::models::schema::bots::dsl::*;
|
||||||
use crate::shared::state::AppState;
|
use crate::shared::state::AppState;
|
||||||
|
use botserver::nvidia::get_system_metrics;
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use sysinfo::System;
|
use sysinfo::System;
|
||||||
|
|
||||||
pub struct StatusPanel {
|
pub struct StatusPanel {
|
||||||
app_state: Arc<AppState>,
|
app_state: Arc<AppState>,
|
||||||
last_update: std::time::Instant,
|
last_update: std::time::Instant,
|
||||||
cached_content: String,
|
cached_content: String,
|
||||||
system: System,
|
system: System,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StatusPanel {
|
impl StatusPanel {
|
||||||
pub fn new(app_state: Arc<AppState>) -> Self {
|
pub fn new(app_state: Arc<AppState>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -20,37 +23,43 @@ impl StatusPanel {
|
||||||
system: System::new_all(),
|
system: System::new_all(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update(&mut self) -> Result<(), std::io::Error> {
|
pub async fn update(&mut self) -> Result<(), std::io::Error> {
|
||||||
if self.last_update.elapsed() < std::time::Duration::from_secs(1) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
self.system.refresh_all();
|
self.system.refresh_all();
|
||||||
self.cached_content = String::new();
|
// Force fresh metrics by using different token counts
|
||||||
|
let tokens = (std::time::SystemTime::now()
|
||||||
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs() % 1000) as usize;
|
||||||
|
let system_metrics = nvidia::get_system_metrics().unwrap_or_default();
|
||||||
|
self.cached_content = self.render(None);
|
||||||
self.last_update = std::time::Instant::now();
|
self.last_update = std::time::Instant::now();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self, selected_bot: Option<String>) -> String {
|
pub fn render(&mut self, selected_bot: Option<String>) -> String {
|
||||||
let mut lines = Vec::new();
|
let mut lines = Vec::new();
|
||||||
self.system.refresh_all();
|
|
||||||
|
// System metrics section
|
||||||
lines.push("╔═══════════════════════════════════════╗".to_string());
|
lines.push("╔═══════════════════════════════════════╗".to_string());
|
||||||
lines.push("║ SYSTEM METRICS ║".to_string());
|
lines.push("║ SYSTEM METRICS ║".to_string());
|
||||||
lines.push("╚═══════════════════════════════════════╝".to_string());
|
lines.push("╚═══════════════════════════════════════╝".to_string());
|
||||||
lines.push("".to_string());
|
lines.push("".to_string());
|
||||||
let system_metrics = match nvidia::get_system_metrics(0, 0) {
|
|
||||||
Ok(metrics) => metrics,
|
self.system.refresh_cpu_all();
|
||||||
Err(_) => nvidia::SystemMetrics::default(),
|
let cpu_usage = self.system.global_cpu_usage();
|
||||||
};
|
let cpu_bar = Self::create_progress_bar(cpu_usage, 20);
|
||||||
let cpu_bar = Self::create_progress_bar(system_metrics.cpu_usage, 20);
|
lines.push(format!(" CPU: {:5.1}% {}", cpu_usage, cpu_bar));
|
||||||
lines.push(format!(
|
let system_metrics = get_system_metrics().unwrap_or_default();
|
||||||
" CPU: {:5.1}% {}",
|
|
||||||
system_metrics.cpu_usage, cpu_bar
|
|
||||||
));
|
|
||||||
if let Some(gpu_usage) = system_metrics.gpu_usage {
|
if let Some(gpu_usage) = system_metrics.gpu_usage {
|
||||||
let gpu_bar = Self::create_progress_bar(gpu_usage, 20);
|
let gpu_bar = Self::create_progress_bar(gpu_usage, 20);
|
||||||
lines.push(format!(" GPU: {:5.1}% {}", gpu_usage, gpu_bar));
|
lines.push(format!(" GPU: {:5.1}% {}", gpu_usage, gpu_bar));
|
||||||
} else {
|
} else {
|
||||||
lines.push(" GPU: Not available".to_string());
|
lines.push(" GPU: Not available".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let total_mem = self.system.total_memory() as f32 / 1024.0 / 1024.0 / 1024.0;
|
let total_mem = self.system.total_memory() as f32 / 1024.0 / 1024.0 / 1024.0;
|
||||||
let used_mem = self.system.used_memory() as f32 / 1024.0 / 1024.0 / 1024.0;
|
let used_mem = self.system.used_memory() as f32 / 1024.0 / 1024.0 / 1024.0;
|
||||||
let mem_percentage = (used_mem / total_mem) * 100.0;
|
let mem_percentage = (used_mem / total_mem) * 100.0;
|
||||||
|
|
@ -59,17 +68,21 @@ impl StatusPanel {
|
||||||
" MEM: {:5.1}% {} ({:.1}/{:.1} GB)",
|
" MEM: {:5.1}% {} ({:.1}/{:.1} GB)",
|
||||||
mem_percentage, mem_bar, used_mem, total_mem
|
mem_percentage, mem_bar, used_mem, total_mem
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// Components status section
|
||||||
lines.push("".to_string());
|
lines.push("".to_string());
|
||||||
lines.push("╔═══════════════════════════════════════╗".to_string());
|
lines.push("╔═══════════════════════════════════════╗".to_string());
|
||||||
lines.push("║ COMPONENTS STATUS ║".to_string());
|
lines.push("║ COMPONENTS STATUS ║".to_string());
|
||||||
lines.push("╚═══════════════════════════════════════╝".to_string());
|
lines.push("╚═══════════════════════════════════════╝".to_string());
|
||||||
lines.push("".to_string());
|
lines.push("".to_string());
|
||||||
|
|
||||||
let components = vec![
|
let components = vec![
|
||||||
("Tables", "postgres", "5432"),
|
("Tables", "postgres", "5432"),
|
||||||
("Cache", "valkey-server", "6379"),
|
("Cache", "valkey-server", "6379"),
|
||||||
("Drive", "minio", "9000"),
|
("Drive", "minio", "9000"),
|
||||||
("LLM", "llama-server", "8081"),
|
("LLM", "llama-server", "8081"),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (comp_name, process, port) in components {
|
for (comp_name, process, port) in components {
|
||||||
let status = if Self::check_component_running(process) {
|
let status = if Self::check_component_running(process) {
|
||||||
format!("🟢 ONLINE [Port: {}]", port)
|
format!("🟢 ONLINE [Port: {}]", port)
|
||||||
|
|
@ -78,11 +91,14 @@ impl StatusPanel {
|
||||||
};
|
};
|
||||||
lines.push(format!(" {:<10} {}", comp_name, status));
|
lines.push(format!(" {:<10} {}", comp_name, status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Active bots section
|
||||||
lines.push("".to_string());
|
lines.push("".to_string());
|
||||||
lines.push("╔═══════════════════════════════════════╗".to_string());
|
lines.push("╔═══════════════════════════════════════╗".to_string());
|
||||||
lines.push("║ ACTIVE BOTS ║".to_string());
|
lines.push("║ ACTIVE BOTS ║".to_string());
|
||||||
lines.push("╚═══════════════════════════════════════╝".to_string());
|
lines.push("╚═══════════════════════════════════════╝".to_string());
|
||||||
lines.push("".to_string());
|
lines.push("".to_string());
|
||||||
|
|
||||||
if let Ok(mut conn) = self.app_state.conn.get() {
|
if let Ok(mut conn) = self.app_state.conn.get() {
|
||||||
match bots
|
match bots
|
||||||
.filter(is_active.eq(true))
|
.filter(is_active.eq(true))
|
||||||
|
|
@ -95,21 +111,15 @@ impl StatusPanel {
|
||||||
} else {
|
} else {
|
||||||
for (bot_name, bot_id) in bot_list {
|
for (bot_name, bot_id) in bot_list {
|
||||||
let marker = if let Some(ref selected) = selected_bot {
|
let marker = if let Some(ref selected) = selected_bot {
|
||||||
if selected == &bot_name {
|
if selected == &bot_name { "►" } else { " " }
|
||||||
"►"
|
} else { " " };
|
||||||
} else {
|
|
||||||
" "
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
" "
|
|
||||||
};
|
|
||||||
lines.push(format!(" {} 🤖 {}", marker, bot_name));
|
lines.push(format!(" {} 🤖 {}", marker, bot_name));
|
||||||
|
|
||||||
if let Some(ref selected) = selected_bot {
|
if let Some(ref selected) = selected_bot {
|
||||||
if selected == &bot_name {
|
if selected == &bot_name {
|
||||||
lines.push("".to_string());
|
lines.push("".to_string());
|
||||||
lines.push(" ┌─ Bot Configuration ─────────┐".to_string());
|
lines.push(" ┌─ Bot Configuration ─────────┐".to_string());
|
||||||
let config_manager =
|
let config_manager = ConfigManager::new(self.app_state.conn.clone());
|
||||||
ConfigManager::new(self.app_state.conn.clone());
|
|
||||||
let llm_model = config_manager
|
let llm_model = config_manager
|
||||||
.get_config(&bot_id, "llm-model", None)
|
.get_config(&bot_id, "llm-model", None)
|
||||||
.unwrap_or_else(|_| "N/A".to_string());
|
.unwrap_or_else(|_| "N/A".to_string());
|
||||||
|
|
@ -135,10 +145,13 @@ impl StatusPanel {
|
||||||
} else {
|
} else {
|
||||||
lines.push(" Database locked".to_string());
|
lines.push(" Database locked".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sessions section
|
||||||
lines.push("".to_string());
|
lines.push("".to_string());
|
||||||
lines.push("╔═══════════════════════════════════════╗".to_string());
|
lines.push("╔═══════════════════════════════════════╗".to_string());
|
||||||
lines.push("║ SESSIONS ║".to_string());
|
lines.push("║ SESSIONS ║".to_string());
|
||||||
lines.push("╚═══════════════════════════════════════╝".to_string());
|
lines.push("╚═══════════════════════════════════════╝".to_string());
|
||||||
|
|
||||||
let session_count = self
|
let session_count = self
|
||||||
.app_state
|
.app_state
|
||||||
.response_channels
|
.response_channels
|
||||||
|
|
@ -146,8 +159,10 @@ impl StatusPanel {
|
||||||
.map(|channels| channels.len())
|
.map(|channels| channels.len())
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
lines.push(format!(" Active Sessions: {}", session_count));
|
lines.push(format!(" Active Sessions: {}", session_count));
|
||||||
|
|
||||||
lines.join("\n")
|
lines.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_progress_bar(percentage: f32, width: usize) -> String {
|
fn create_progress_bar(percentage: f32, width: usize) -> String {
|
||||||
let filled = (percentage / 100.0 * width as f32).round() as usize;
|
let filled = (percentage / 100.0 * width as f32).round() as usize;
|
||||||
let empty = width.saturating_sub(filled);
|
let empty = width.saturating_sub(filled);
|
||||||
|
|
@ -155,6 +170,7 @@ impl StatusPanel {
|
||||||
let empty_chars = "░".repeat(empty);
|
let empty_chars = "░".repeat(empty);
|
||||||
format!("[{}{}]", filled_chars, empty_chars)
|
format!("[{}{}]", filled_chars, empty_chars)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_component_running(process_name: &str) -> bool {
|
pub fn check_component_running(process_name: &str) -> bool {
|
||||||
std::process::Command::new("pgrep")
|
std::process::Command::new("pgrep")
|
||||||
.arg("-f")
|
.arg("-f")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue