feat: add sysinfo dependency and system metrics support
Added the sysinfo crate (v0.37.2) to gather system metrics. This includes: - New dependencies: sysinfo, ntapi, objc2-core-foundation, objc2-io-kit - Updated windows-core to specific version 0.62.2 - Initial system metrics integration in bot module The change enables monitoring system resources which will be used for performance optimization and health monitoring.
This commit is contained in:
parent
ac9c1509d5
commit
dc0e0a9c51
6 changed files with 243 additions and 4 deletions
110
Cargo.lock
generated
110
Cargo.lock
generated
|
|
@ -1151,6 +1151,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"smartstring",
|
"smartstring",
|
||||||
|
"sysinfo",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"time",
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
@ -2821,7 +2822,7 @@ dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-core",
|
"windows-core 0.62.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -3642,6 +3643,15 @@ dependencies = [
|
||||||
"nom 8.0.0",
|
"nom 8.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ntapi"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.50.3"
|
version = "0.50.3"
|
||||||
|
|
@ -3695,6 +3705,25 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-core-foundation"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-io-kit"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.32.2"
|
version = "0.32.2"
|
||||||
|
|
@ -5229,6 +5258,20 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sysinfo"
|
||||||
|
version = "0.37.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "16607d5caffd1c07ce073528f9ed972d88db15dd44023fa57142963be3feb11f"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"memchr",
|
||||||
|
"ntapi",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
"objc2-io-kit",
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-configuration"
|
name = "system-configuration"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
|
@ -6144,6 +6187,41 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.61.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
|
||||||
|
dependencies = [
|
||||||
|
"windows-collections",
|
||||||
|
"windows-core 0.61.2",
|
||||||
|
"windows-future",
|
||||||
|
"windows-link 0.1.3",
|
||||||
|
"windows-numerics",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-collections"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.61.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.61.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||||
|
dependencies = [
|
||||||
|
"windows-implement",
|
||||||
|
"windows-interface",
|
||||||
|
"windows-link 0.1.3",
|
||||||
|
"windows-result 0.3.4",
|
||||||
|
"windows-strings 0.4.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.62.2"
|
version = "0.62.2"
|
||||||
|
|
@ -6157,6 +6235,17 @@ dependencies = [
|
||||||
"windows-strings 0.5.1",
|
"windows-strings 0.5.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-future"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.61.2",
|
||||||
|
"windows-link 0.1.3",
|
||||||
|
"windows-threading",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-implement"
|
name = "windows-implement"
|
||||||
version = "0.60.2"
|
version = "0.60.2"
|
||||||
|
|
@ -6191,6 +6280,16 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-numerics"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.61.2",
|
||||||
|
"windows-link 0.1.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-registry"
|
name = "windows-registry"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
|
@ -6331,6 +6430,15 @@ dependencies = [
|
||||||
"windows_x86_64_msvc 0.53.1",
|
"windows_x86_64_msvc 0.53.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-threading"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link 0.1.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.42.2"
|
version = "0.42.2"
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
sha2 = "0.10.9"
|
sha2 = "0.10.9"
|
||||||
smartstring = "1.0"
|
smartstring = "1.0"
|
||||||
|
sysinfo = "0.37.2"
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
time = "0.3.44"
|
time = "0.3.44"
|
||||||
tokio = { version = "1.41", features = ["full"] }
|
tokio = { version = "1.41", features = ["full"] }
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
use crate::config::ConfigManager;
|
use crate::config::ConfigManager;
|
||||||
use crate::drive_monitor::DriveMonitor;
|
use crate::drive_monitor::DriveMonitor;
|
||||||
use crate::llm_models;
|
use crate::llm_models;
|
||||||
|
use crate::nvidia::get_system_metrics;
|
||||||
use crate::shared::models::{BotResponse, Suggestion, UserMessage, UserSession};
|
use crate::shared::models::{BotResponse, Suggestion, UserMessage, UserSession};
|
||||||
use crate::shared::state::AppState;
|
use crate::shared::state::AppState;
|
||||||
use actix_web::{web, HttpRequest, HttpResponse, Result};
|
use actix_web::{web, HttpRequest, HttpResponse, Result};
|
||||||
use actix_ws::Message as WsMessage;
|
use actix_ws::Message as WsMessage;
|
||||||
use chrono::Utc;
|
use chrono::{Utc};
|
||||||
use diesel::PgConnection;
|
use diesel::PgConnection;
|
||||||
use log::{error, info, trace, warn};
|
use log::{error, info, trace, warn};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
use tokio::time::Instant;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio::sync::Mutex as AsyncMutex;
|
use tokio::sync::Mutex as AsyncMutex;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
@ -436,9 +439,10 @@ impl BotOrchestrator {
|
||||||
response_tx.send(thinking_response).await?;
|
response_tx.send(thinking_response).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let prompt_clone = prompt.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(e) = llm
|
if let Err(e) = llm
|
||||||
.generate_stream(&prompt, &serde_json::Value::Null, stream_tx)
|
.generate_stream(&prompt_clone, &serde_json::Value::Null, stream_tx)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
error!("LLM streaming error: {}", e);
|
error!("LLM streaming error: {}", e);
|
||||||
|
|
@ -450,8 +454,32 @@ impl BotOrchestrator {
|
||||||
let mut in_analysis = false;
|
let mut in_analysis = false;
|
||||||
let mut chunk_count = 0;
|
let mut chunk_count = 0;
|
||||||
let mut first_word_received = false;
|
let mut first_word_received = false;
|
||||||
|
let mut last_progress_update = Instant::now();
|
||||||
|
let progress_interval = Duration::from_secs(1);
|
||||||
|
|
||||||
|
// Calculate initial token count
|
||||||
|
let initial_tokens = crate::shared::utils::estimate_token_count(&prompt);
|
||||||
let config_manager = ConfigManager::new(Arc::clone(&self.state.conn));
|
let config_manager = ConfigManager::new(Arc::clone(&self.state.conn));
|
||||||
|
let max_context_size = config_manager
|
||||||
|
.get_config(
|
||||||
|
&Uuid::parse_str(&message.bot_id).unwrap_or_default(),
|
||||||
|
"llm-server-ctx-size",
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.parse::<usize>()
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
// Show initial progress
|
||||||
|
if let Ok(metrics) = get_system_metrics(initial_tokens, max_context_size) {
|
||||||
|
eprintln!(
|
||||||
|
"\nNVIDIA: {:.1}% | CPU: {:.1}% | Tokens: {}/{}",
|
||||||
|
metrics.gpu_usage.unwrap_or(0.0),
|
||||||
|
metrics.cpu_usage,
|
||||||
|
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(),
|
||||||
|
|
@ -498,6 +526,21 @@ impl BotOrchestrator {
|
||||||
if !in_analysis {
|
if !in_analysis {
|
||||||
full_response.push_str(&chunk);
|
full_response.push_str(&chunk);
|
||||||
|
|
||||||
|
// Update progress if interval elapsed
|
||||||
|
if last_progress_update.elapsed() >= progress_interval {
|
||||||
|
let current_tokens = initial_tokens + crate::shared::utils::estimate_token_count(&full_response);
|
||||||
|
if let Ok(metrics) = get_system_metrics(current_tokens, max_context_size) {
|
||||||
|
eprintln!(
|
||||||
|
"\nNVIDIA: {:.1}% | CPU: {:.1}% | Tokens: {}/{}",
|
||||||
|
metrics.gpu_usage.unwrap_or(0.0),
|
||||||
|
metrics.cpu_usage,
|
||||||
|
current_tokens,
|
||||||
|
max_context_size
|
||||||
|
);
|
||||||
|
}
|
||||||
|
last_progress_update = Instant::now();
|
||||||
|
}
|
||||||
|
|
||||||
let partial = BotResponse {
|
let partial = BotResponse {
|
||||||
bot_id: message.bot_id.clone(),
|
bot_id: message.bot_id.clone(),
|
||||||
user_id: message.user_id.clone(),
|
user_id: message.user_id.clone(),
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,4 @@ pub mod tests;
|
||||||
pub mod web_automation;
|
pub mod web_automation;
|
||||||
pub mod web_server;
|
pub mod web_server;
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
|
pub mod nvidia;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ pub mod tests;
|
||||||
#[cfg(feature = "web_automation")]
|
#[cfg(feature = "web_automation")]
|
||||||
mod web_automation;
|
mod web_automation;
|
||||||
mod web_server;
|
mod web_server;
|
||||||
|
mod nvidia;
|
||||||
|
|
||||||
use crate::auth::auth_handler;
|
use crate::auth::auth_handler;
|
||||||
use crate::automation::AutomationService;
|
use crate::automation::AutomationService;
|
||||||
|
|
|
||||||
86
src/nvidia/mod.rs
Normal file
86
src/nvidia/mod.rs
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use log::warn;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use sysinfo::{System};
|
||||||
|
|
||||||
|
/// System monitoring data
|
||||||
|
pub struct SystemMetrics {
|
||||||
|
pub gpu_usage: Option<f32>,
|
||||||
|
pub cpu_usage: f32,
|
||||||
|
pub token_ratio: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets current system metrics
|
||||||
|
pub fn get_system_metrics(current_tokens: usize, max_tokens: usize) -> Result<SystemMetrics> {
|
||||||
|
let mut sys = System::new();
|
||||||
|
sys.refresh_cpu_usage();
|
||||||
|
|
||||||
|
// Get CPU usage (average across all cores)
|
||||||
|
let cpu_usage = sys.global_cpu_usage();
|
||||||
|
|
||||||
|
// Get GPU usage if available
|
||||||
|
let gpu_usage = if has_nvidia_gpu() {
|
||||||
|
get_gpu_utilization()?.get("gpu").copied()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate token ratio
|
||||||
|
let token_ratio = if max_tokens > 0 {
|
||||||
|
current_tokens as f32 / max_tokens as f32 * 100.0
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(SystemMetrics {
|
||||||
|
gpu_usage,
|
||||||
|
cpu_usage,
|
||||||
|
token_ratio,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if NVIDIA GPU is available
|
||||||
|
pub fn has_nvidia_gpu() -> bool {
|
||||||
|
match std::process::Command::new("nvidia-smi")
|
||||||
|
.arg("--query-gpu=utilization.gpu")
|
||||||
|
.arg("--format=csv,noheader,nounits")
|
||||||
|
.output()
|
||||||
|
{
|
||||||
|
Ok(output) => output.status.success(),
|
||||||
|
Err(_) => {
|
||||||
|
warn!("No NVIDIA GPU detected or nvidia-smi not available");
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets current GPU utilization percentages
|
||||||
|
pub fn get_gpu_utilization() -> Result<HashMap<String, f32>> {
|
||||||
|
let output = std::process::Command::new("nvidia-smi")
|
||||||
|
.arg("--query-gpu=utilization.gpu,utilization.memory")
|
||||||
|
.arg("--format=csv,noheader,nounits")
|
||||||
|
.output()?;
|
||||||
|
|
||||||
|
if !output.status.success() {
|
||||||
|
return Err(anyhow::anyhow!("Failed to query GPU utilization"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let output_str = String::from_utf8(output.stdout)?;
|
||||||
|
let mut util = HashMap::new();
|
||||||
|
|
||||||
|
for line in output_str.lines() {
|
||||||
|
let parts: Vec<&str> = line.split(',').collect();
|
||||||
|
if parts.len() >= 2 {
|
||||||
|
util.insert(
|
||||||
|
"gpu".to_string(),
|
||||||
|
parts[0].trim().parse::<f32>().unwrap_or(0.0),
|
||||||
|
);
|
||||||
|
util.insert(
|
||||||
|
"memory".to_string(),
|
||||||
|
parts[1].trim().parse::<f32>().unwrap_or(0.0),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(util)
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue