mirror of
https://github.com/RGBCube/superfreq
synced 2025-07-27 17:07:44 +00:00
core: improve formatting & display for info
command
This commit is contained in:
parent
166dc5a6a5
commit
fad56e6e1e
4 changed files with 457 additions and 80 deletions
|
@ -69,10 +69,7 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
Some(path)
|
||||
} else {
|
||||
// Check standard config paths
|
||||
let default_paths = [
|
||||
"/etc/superfreq/config.toml",
|
||||
"/etc/superfreq.toml",
|
||||
];
|
||||
let default_paths = ["/etc/superfreq/config.toml", "/etc/superfreq.toml"];
|
||||
|
||||
default_paths
|
||||
.iter()
|
||||
|
@ -80,24 +77,26 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
.map(|path| (*path).to_string())
|
||||
};
|
||||
|
||||
let mut config_watcher = if let Some(path) = config_file_path { match ConfigWatcher::new(&path) {
|
||||
Ok(watcher) => {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Info,
|
||||
&format!("Watching config file: {path}"),
|
||||
);
|
||||
Some(watcher)
|
||||
let mut config_watcher = if let Some(path) = config_file_path {
|
||||
match ConfigWatcher::new(&path) {
|
||||
Ok(watcher) => {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Info,
|
||||
&format!("Watching config file: {path}"),
|
||||
);
|
||||
Some(watcher)
|
||||
}
|
||||
Err(e) => {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Warning,
|
||||
&format!("Failed to initialize config file watcher: {e}"),
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Warning,
|
||||
&format!("Failed to initialize config file watcher: {e}"),
|
||||
);
|
||||
None
|
||||
}
|
||||
} } else {
|
||||
} else {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Warning,
|
||||
|
|
266
src/main.rs
266
src/main.rs
|
@ -91,89 +91,237 @@ fn main() {
|
|||
};
|
||||
|
||||
let command_result = match cli.command {
|
||||
// TODO: This will be moved to a different module in the future.
|
||||
Some(Commands::Info) => match monitor::collect_system_report(&config) {
|
||||
Ok(report) => {
|
||||
println!("--- System Information ---");
|
||||
println!("CPU Model: {}", report.system_info.cpu_model);
|
||||
println!("Architecture: {}", report.system_info.architecture);
|
||||
// Format section headers with proper centering
|
||||
let format_section = |title: &str| {
|
||||
let title_len = title.len();
|
||||
let total_width = title_len + 8; // 8 is for padding (4 on each side)
|
||||
let separator = "═".repeat(total_width);
|
||||
|
||||
println!("\n╔{}╗", separator);
|
||||
|
||||
// Calculate centering
|
||||
println!("║ {} ║", title);
|
||||
|
||||
println!("╚{}╝", separator);
|
||||
};
|
||||
|
||||
format_section("System Information");
|
||||
println!("CPU Model: {}", report.system_info.cpu_model);
|
||||
println!("Architecture: {}", report.system_info.architecture);
|
||||
println!(
|
||||
"Linux Distribution: {}",
|
||||
report.system_info.linux_distribution
|
||||
);
|
||||
println!("Timestamp: {:?}", report.timestamp);
|
||||
|
||||
println!("\n--- CPU Global Info ---");
|
||||
println!("Current Governor: {:?}", report.cpu_global.current_governor);
|
||||
// Format timestamp in a readable way
|
||||
println!(
|
||||
"Available Governors: {:?}",
|
||||
"Current Time: {}",
|
||||
chrono::Local::now().format("%Y-%m-%d %H:%M:%S")
|
||||
);
|
||||
|
||||
format_section("CPU Global Info");
|
||||
println!(
|
||||
"Current Governor: {}",
|
||||
report
|
||||
.cpu_global
|
||||
.current_governor
|
||||
.as_deref()
|
||||
.unwrap_or("N/A")
|
||||
);
|
||||
println!(
|
||||
"Available Governors: {}",
|
||||
report.cpu_global.available_governors.join(", ")
|
||||
);
|
||||
println!("Turbo Status: {:?}", report.cpu_global.turbo_status);
|
||||
println!("EPP: {:?}", report.cpu_global.epp);
|
||||
println!("EPB: {:?}", report.cpu_global.epb);
|
||||
println!("Platform Profile: {:?}", report.cpu_global.platform_profile);
|
||||
println!(
|
||||
"Average CPU Temperature: {}",
|
||||
"Turbo Status: {}",
|
||||
match report.cpu_global.turbo_status {
|
||||
Some(true) => "Enabled",
|
||||
Some(false) => "Disabled",
|
||||
None => "Unknown",
|
||||
}
|
||||
);
|
||||
|
||||
println!(
|
||||
"EPP: {}",
|
||||
report.cpu_global.epp.as_deref().unwrap_or("N/A")
|
||||
);
|
||||
println!(
|
||||
"EPB: {}",
|
||||
report.cpu_global.epb.as_deref().unwrap_or("N/A")
|
||||
);
|
||||
println!(
|
||||
"Platform Profile: {}",
|
||||
report
|
||||
.cpu_global
|
||||
.platform_profile
|
||||
.as_deref()
|
||||
.unwrap_or("N/A")
|
||||
);
|
||||
println!(
|
||||
"CPU Temperature: {}",
|
||||
report.cpu_global.average_temperature_celsius.map_or_else(
|
||||
|| "N/A (CPU temperature sensor not detected)".to_string(),
|
||||
|t| format!("{t:.1}°C")
|
||||
|| "N/A (No sensor detected)".to_string(),
|
||||
|t| format!("{:.1}°C", t)
|
||||
)
|
||||
);
|
||||
|
||||
println!("\n--- CPU Core Info ---");
|
||||
for core_info in report.cpu_cores {
|
||||
format_section("CPU Core Info");
|
||||
|
||||
// Get max core ID length for padding
|
||||
let max_core_id_len = report
|
||||
.cpu_cores
|
||||
.last()
|
||||
.map_or(1, |core| core.core_id.to_string().len());
|
||||
|
||||
// Table headers
|
||||
println!(
|
||||
" {:>width$} │ {:^10} │ {:^10} │ {:^10} │ {:^7} │ {:^9}",
|
||||
"Core",
|
||||
"Current",
|
||||
"Min",
|
||||
"Max",
|
||||
"Usage",
|
||||
"Temp",
|
||||
width = max_core_id_len + 4
|
||||
);
|
||||
println!(
|
||||
" {:─>width$}──┼─{:─^10}─┼─{:─^10}─┼─{:─^10}─┼─{:─^7}─┼─{:─^9}",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
width = max_core_id_len + 4
|
||||
);
|
||||
|
||||
for core_info in &report.cpu_cores {
|
||||
// Format frequencies: if current > max, show in a special way
|
||||
let current_freq = match core_info.current_frequency_mhz {
|
||||
Some(freq) => {
|
||||
let max_freq = core_info.max_frequency_mhz.unwrap_or(0);
|
||||
if freq > max_freq && max_freq > 0 {
|
||||
// Special format for boosted frequencies
|
||||
format!("{}*", freq)
|
||||
} else {
|
||||
format!("{}", freq)
|
||||
}
|
||||
}
|
||||
None => "N/A".to_string(),
|
||||
};
|
||||
|
||||
// CPU core display
|
||||
println!(
|
||||
" Core {}: Current Freq: {:?} MHz, Min Freq: {:?} MHz, Max Freq: {:?} MHz, Usage: {:?}%, Temp: {:?}°C",
|
||||
" Core {:<width$} │ {:>10} │ {:>10} │ {:>10} │ {:>7} │ {:>9}",
|
||||
core_info.core_id,
|
||||
core_info
|
||||
.current_frequency_mhz
|
||||
.map_or_else(|| "N/A".to_string(), |f| f.to_string()),
|
||||
core_info
|
||||
.min_frequency_mhz
|
||||
.map_or_else(|| "N/A".to_string(), |f| f.to_string()),
|
||||
core_info
|
||||
.max_frequency_mhz
|
||||
.map_or_else(|| "N/A".to_string(), |f| f.to_string()),
|
||||
core_info
|
||||
.usage_percent
|
||||
.map_or_else(|| "N/A".to_string(), |f| format!("{f:.1}")),
|
||||
core_info
|
||||
.temperature_celsius
|
||||
.map_or_else(|| "N/A".to_string(), |f| format!("{f:.1}"))
|
||||
format!("{} MHz", current_freq),
|
||||
format!(
|
||||
"{} MHz",
|
||||
core_info
|
||||
.min_frequency_mhz
|
||||
.map_or_else(|| "N/A".to_string(), |f| f.to_string())
|
||||
),
|
||||
format!(
|
||||
"{} MHz",
|
||||
core_info
|
||||
.max_frequency_mhz
|
||||
.map_or_else(|| "N/A".to_string(), |f| f.to_string())
|
||||
),
|
||||
format!(
|
||||
"{}%",
|
||||
core_info
|
||||
.usage_percent
|
||||
.map_or_else(|| "N/A".to_string(), |f| format!("{:.1}", f))
|
||||
),
|
||||
format!(
|
||||
"{}°C",
|
||||
core_info
|
||||
.temperature_celsius
|
||||
.map_or_else(|| "N/A".to_string(), |f| format!("{:.1}", f))
|
||||
),
|
||||
width = max_core_id_len
|
||||
);
|
||||
}
|
||||
|
||||
println!("\n--- Battery Info ---");
|
||||
if report.batteries.is_empty() {
|
||||
println!(" No batteries found or all are ignored.");
|
||||
} else {
|
||||
for battery_info in report.batteries {
|
||||
println!(
|
||||
" Battery {}: AC Connected: {}, State: {:?}, Capacity: {:?}%, Power Rate: {:?} W, Charge Thresholds: {:?}-{:?}",
|
||||
battery_info.name,
|
||||
battery_info.ac_connected,
|
||||
battery_info.charging_state.as_deref().unwrap_or("N/A"),
|
||||
battery_info
|
||||
.capacity_percent
|
||||
.map_or_else(|| "N/A".to_string(), |c| c.to_string()),
|
||||
battery_info
|
||||
.power_rate_watts
|
||||
.map_or_else(|| "N/A".to_string(), |p| format!("{p:.2}")),
|
||||
battery_info
|
||||
.charge_start_threshold
|
||||
.map_or_else(|| "N/A".to_string(), |t| t.to_string()),
|
||||
battery_info
|
||||
.charge_stop_threshold
|
||||
.map_or_else(|| "N/A".to_string(), |t| t.to_string())
|
||||
);
|
||||
// Only display battery info for systems that have real batteries
|
||||
// Skip this section entirely on desktop systems
|
||||
if !report.batteries.is_empty() {
|
||||
let has_real_batteries = report.batteries.iter().any(|b| {
|
||||
// Check if any battery has actual battery data
|
||||
// (as opposed to peripherals like wireless mice)
|
||||
b.capacity_percent.is_some() || b.power_rate_watts.is_some()
|
||||
});
|
||||
|
||||
if has_real_batteries {
|
||||
format_section("Battery Info");
|
||||
for battery_info in &report.batteries {
|
||||
// Check if this appears to be a real system battery
|
||||
if battery_info.capacity_percent.is_some()
|
||||
|| battery_info.power_rate_watts.is_some()
|
||||
{
|
||||
let power_status = if battery_info.ac_connected {
|
||||
"Connected to AC"
|
||||
} else {
|
||||
"Running on Battery"
|
||||
};
|
||||
|
||||
println!("Battery {}:", battery_info.name);
|
||||
println!(" Power Status: {power_status}");
|
||||
println!(
|
||||
" State: {}",
|
||||
battery_info.charging_state.as_deref().unwrap_or("Unknown")
|
||||
);
|
||||
|
||||
if let Some(capacity) = battery_info.capacity_percent {
|
||||
println!(" Capacity: {capacity}%");
|
||||
}
|
||||
|
||||
if let Some(power) = battery_info.power_rate_watts {
|
||||
let direction = if power >= 0.0 {
|
||||
"charging"
|
||||
} else {
|
||||
"discharging"
|
||||
};
|
||||
println!(
|
||||
" Power Rate: {:.2} W ({})",
|
||||
power.abs(),
|
||||
direction
|
||||
);
|
||||
}
|
||||
|
||||
// Display charge thresholds if available
|
||||
if battery_info.charge_start_threshold.is_some()
|
||||
|| battery_info.charge_stop_threshold.is_some()
|
||||
{
|
||||
println!(
|
||||
" Charge Thresholds: {}-{}",
|
||||
battery_info
|
||||
.charge_start_threshold
|
||||
.map_or_else(|| "N/A".to_string(), |t| t.to_string()),
|
||||
battery_info
|
||||
.charge_stop_threshold
|
||||
.map_or_else(|| "N/A".to_string(), |t| t.to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("\n--- System Load ---");
|
||||
format_section("System Load");
|
||||
println!(
|
||||
"Load Average (1m, 5m, 15m): {:.2}, {:.2}, {:.2}",
|
||||
report.system_load.load_avg_1min,
|
||||
report.system_load.load_avg_5min,
|
||||
"Load Average (1m): {:.2}",
|
||||
report.system_load.load_avg_1min
|
||||
);
|
||||
println!(
|
||||
"Load Average (5m): {:.2}",
|
||||
report.system_load.load_avg_5min
|
||||
);
|
||||
println!(
|
||||
"Load Average (15m): {:.2}",
|
||||
report.system_load.load_avg_15min
|
||||
);
|
||||
Ok(())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue