mirror of
https://github.com/RGBCube/superfreq
synced 2025-07-27 17:07:44 +00:00
core: switch to log
for proper logging
This commit is contained in:
parent
02a11eb9db
commit
b7f374c32c
5 changed files with 210 additions and 166 deletions
165
src/daemon.rs
165
src/daemon.rs
|
@ -4,6 +4,7 @@ use crate::conflict;
|
|||
use crate::core::SystemReport;
|
||||
use crate::engine;
|
||||
use crate::monitor;
|
||||
use log::{LevelFilter, debug, error, info, warn};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::sync::Arc;
|
||||
|
@ -19,20 +20,23 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
config.daemon.log_level
|
||||
};
|
||||
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Info,
|
||||
"Starting superfreq daemon...",
|
||||
);
|
||||
// Get the appropriate level filter
|
||||
let level_filter = match effective_log_level {
|
||||
LogLevel::Error => LevelFilter::Error,
|
||||
LogLevel::Warning => LevelFilter::Warn,
|
||||
LogLevel::Info => LevelFilter::Info,
|
||||
LogLevel::Debug => LevelFilter::Debug,
|
||||
};
|
||||
|
||||
// Update the log level filter if needed, without re-initializing the logger
|
||||
log::set_max_level(level_filter);
|
||||
|
||||
info!("Starting superfreq daemon...");
|
||||
|
||||
// Check for conflicts with other power management services
|
||||
let conflicts = conflict::detect_conflicts();
|
||||
if conflicts.has_conflicts() {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Warning,
|
||||
&conflicts.get_conflict_message(),
|
||||
);
|
||||
warn!("{}", conflicts.get_conflict_message());
|
||||
}
|
||||
|
||||
// Create a flag that will be set to true when a signal is received
|
||||
|
@ -41,27 +45,19 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
|
||||
// Set up signal handlers
|
||||
ctrlc::set_handler(move || {
|
||||
println!("Received shutdown signal, exiting...");
|
||||
info!("Received shutdown signal, exiting...");
|
||||
r.store(false, Ordering::SeqCst);
|
||||
})
|
||||
.expect("Error setting Ctrl-C handler");
|
||||
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Info,
|
||||
&format!(
|
||||
"Daemon initialized with poll interval: {}s",
|
||||
config.daemon.poll_interval_sec
|
||||
),
|
||||
info!(
|
||||
"Daemon initialized with poll interval: {}s",
|
||||
config.daemon.poll_interval_sec
|
||||
);
|
||||
|
||||
// Set up stats file if configured
|
||||
if let Some(stats_path) = &config.daemon.stats_file_path {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Info,
|
||||
&format!("Stats will be written to: {stats_path}"),
|
||||
);
|
||||
info!("Stats will be written to: {stats_path}");
|
||||
}
|
||||
|
||||
// Initialize config file watcher if a path is available
|
||||
|
@ -80,28 +76,16 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
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}"),
|
||||
);
|
||||
info!("Watching config file: {path}");
|
||||
Some(watcher)
|
||||
}
|
||||
Err(e) => {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Warning,
|
||||
&format!("Failed to initialize config file watcher: {e}"),
|
||||
);
|
||||
warn!("Failed to initialize config file watcher: {e}");
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Warning,
|
||||
"No config file found to watch for changes.",
|
||||
);
|
||||
warn!("No config file found to watch for changes.");
|
||||
None
|
||||
};
|
||||
|
||||
|
@ -119,11 +103,7 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
if let Some(config_result) = watcher.check_for_changes() {
|
||||
match config_result {
|
||||
Ok(new_config) => {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Info,
|
||||
"Config file changed, updating configuration",
|
||||
);
|
||||
info!("Config file changed, updating configuration");
|
||||
config = new_config;
|
||||
// Reset polling interval after config change
|
||||
current_poll_interval = config.daemon.poll_interval_sec;
|
||||
|
@ -131,11 +111,7 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
last_settings_change = Instant::now();
|
||||
}
|
||||
Err(e) => {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Error,
|
||||
&format!("Error loading new configuration: {e}"),
|
||||
);
|
||||
error!("Error loading new configuration: {e}");
|
||||
// Continue with existing config
|
||||
}
|
||||
}
|
||||
|
@ -144,11 +120,7 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
|
||||
match monitor::collect_system_report(&config) {
|
||||
Ok(report) => {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Debug,
|
||||
"Collected system report, applying settings...",
|
||||
);
|
||||
debug!("Collected system report, applying settings...");
|
||||
|
||||
// Determine current system state
|
||||
let current_state = determine_system_state(&report);
|
||||
|
@ -156,40 +128,24 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
// Update the stats file if configured
|
||||
if let Some(stats_path) = &config.daemon.stats_file_path {
|
||||
if let Err(e) = write_stats_file(stats_path, &report) {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Error,
|
||||
&format!("Failed to write stats file: {e}"),
|
||||
);
|
||||
error!("Failed to write stats file: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
match engine::determine_and_apply_settings(&report, &config, None) {
|
||||
Ok(()) => {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Debug,
|
||||
"Successfully applied system settings",
|
||||
);
|
||||
debug!("Successfully applied system settings");
|
||||
|
||||
// If system state changed or settings were applied differently, record the time
|
||||
if current_state != last_system_state {
|
||||
last_settings_change = Instant::now();
|
||||
last_system_state = current_state.clone();
|
||||
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Info,
|
||||
&format!("System state changed to: {current_state:?}"),
|
||||
);
|
||||
info!("System state changed to: {current_state:?}");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Error,
|
||||
&format!("Error applying system settings: {e}"),
|
||||
);
|
||||
error!("Error applying system settings: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,25 +158,13 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
current_poll_interval =
|
||||
(current_poll_interval * 2).min(config.daemon.max_poll_interval_sec);
|
||||
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Debug,
|
||||
&format!(
|
||||
"Adaptive polling: increasing interval to {current_poll_interval}s"
|
||||
),
|
||||
);
|
||||
debug!("Adaptive polling: increasing interval to {current_poll_interval}s");
|
||||
} else if time_since_change < 10 {
|
||||
// If we've had recent changes, decrease the interval (down to min)
|
||||
current_poll_interval =
|
||||
(current_poll_interval / 2).max(config.daemon.min_poll_interval_sec);
|
||||
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Debug,
|
||||
&format!(
|
||||
"Adaptive polling: decreasing interval to {current_poll_interval}s"
|
||||
),
|
||||
);
|
||||
debug!("Adaptive polling: decreasing interval to {current_poll_interval}s");
|
||||
}
|
||||
} else {
|
||||
// If not adaptive, use the configured poll interval
|
||||
|
@ -236,19 +180,11 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
current_poll_interval = (current_poll_interval * battery_multiplier)
|
||||
.min(config.daemon.max_poll_interval_sec);
|
||||
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Debug,
|
||||
"On battery power, increasing poll interval to save energy",
|
||||
);
|
||||
debug!("On battery power, increasing poll interval to save energy");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Error,
|
||||
&format!("Error collecting system report: {e}"),
|
||||
);
|
||||
error!("Error collecting system report: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,39 +193,22 @@ pub fn run_daemon(mut config: AppConfig, verbose: bool) -> Result<(), Box<dyn st
|
|||
let poll_duration = Duration::from_secs(current_poll_interval);
|
||||
if elapsed < poll_duration {
|
||||
let sleep_time = poll_duration - elapsed;
|
||||
log_message(
|
||||
&effective_log_level,
|
||||
LogLevel::Debug,
|
||||
&format!("Sleeping for {}s until next cycle", sleep_time.as_secs()),
|
||||
);
|
||||
debug!("Sleeping for {}s until next cycle", sleep_time.as_secs());
|
||||
std::thread::sleep(sleep_time);
|
||||
}
|
||||
}
|
||||
|
||||
log_message(&effective_log_level, LogLevel::Info, "Daemon stopped");
|
||||
info!("Daemon stopped");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Log a message based on the current log level
|
||||
fn log_message(effective_level: &LogLevel, msg_level: LogLevel, message: &str) {
|
||||
// Only log messages at or above the effective log level
|
||||
let should_log = match effective_level {
|
||||
LogLevel::Error => matches!(msg_level, LogLevel::Error),
|
||||
LogLevel::Warning => matches!(msg_level, LogLevel::Error | LogLevel::Warning),
|
||||
LogLevel::Info => matches!(
|
||||
msg_level,
|
||||
LogLevel::Error | LogLevel::Warning | LogLevel::Info
|
||||
),
|
||||
LogLevel::Debug => true,
|
||||
};
|
||||
|
||||
if should_log {
|
||||
match msg_level {
|
||||
LogLevel::Error => eprintln!("ERROR: {message}"),
|
||||
LogLevel::Warning => eprintln!("WARNING: {message}"),
|
||||
LogLevel::Info => println!("INFO: {message}"),
|
||||
LogLevel::Debug => println!("DEBUG: {message}"),
|
||||
}
|
||||
/// Initialize the logger with the appropriate level
|
||||
const fn get_log_level_filter(log_level: LogLevel) -> LevelFilter {
|
||||
match log_level {
|
||||
LogLevel::Error => LevelFilter::Error,
|
||||
LogLevel::Warning => LevelFilter::Warn,
|
||||
LogLevel::Info => LevelFilter::Info,
|
||||
LogLevel::Debug => LevelFilter::Debug,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::config::{AppConfig, ProfileConfig};
|
|||
use crate::core::{OperationalMode, SystemReport, TurboSetting};
|
||||
use crate::cpu::{self};
|
||||
use crate::util::error::EngineError;
|
||||
use log::{debug, info};
|
||||
|
||||
/// Determines the appropriate CPU profile based on power status or forced mode,
|
||||
/// and applies the settings using functions from the `cpu` module.
|
||||
|
@ -12,8 +13,8 @@ pub fn determine_and_apply_settings(
|
|||
) -> Result<(), EngineError> {
|
||||
// First, check if there's a governor override set
|
||||
if let Some(override_governor) = cpu::get_governor_override() {
|
||||
println!(
|
||||
"Engine: Governor override is active: '{}'. Setting governor.",
|
||||
info!(
|
||||
"Governor override is active: '{}'. Setting governor.",
|
||||
override_governor.trim()
|
||||
);
|
||||
cpu::set_governor(override_governor.trim(), None)?;
|
||||
|
@ -24,11 +25,11 @@ pub fn determine_and_apply_settings(
|
|||
if let Some(mode) = force_mode {
|
||||
match mode {
|
||||
OperationalMode::Powersave => {
|
||||
println!("Engine: Forced Powersave mode selected. Applying 'battery' profile.");
|
||||
info!("Forced Powersave mode selected. Applying 'battery' profile.");
|
||||
selected_profile_config = &config.battery;
|
||||
}
|
||||
OperationalMode::Performance => {
|
||||
println!("Engine: Forced Performance mode selected. Applying 'charger' profile.");
|
||||
info!("Forced Performance mode selected. Applying 'charger' profile.");
|
||||
selected_profile_config = &config.charger;
|
||||
}
|
||||
}
|
||||
|
@ -41,28 +42,25 @@ pub fn determine_and_apply_settings(
|
|||
report.batteries.is_empty() || report.batteries.first().is_some_and(|b| b.ac_connected);
|
||||
|
||||
if on_ac_power {
|
||||
println!("Engine: On AC power, selecting Charger profile.");
|
||||
info!("On AC power, selecting Charger profile.");
|
||||
selected_profile_config = &config.charger;
|
||||
} else {
|
||||
println!("Engine: On Battery power, selecting Battery profile.");
|
||||
info!("On Battery power, selecting Battery profile.");
|
||||
selected_profile_config = &config.battery;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply settings from selected_profile_config
|
||||
// TODO: The println! statements are for temporary debugging/logging
|
||||
// and we'd like to replace them with proper logging in the future.
|
||||
|
||||
if let Some(governor) = &selected_profile_config.governor {
|
||||
println!("Engine: Setting governor to '{governor}'");
|
||||
info!("Setting governor to '{governor}'");
|
||||
cpu::set_governor(governor, None)?;
|
||||
}
|
||||
|
||||
if let Some(turbo_setting) = selected_profile_config.turbo {
|
||||
println!("Engine: Setting turbo to '{turbo_setting:?}'");
|
||||
info!("Setting turbo to '{turbo_setting:?}'");
|
||||
match turbo_setting {
|
||||
TurboSetting::Auto => {
|
||||
println!("Engine: Managing turbo in auto mode based on system conditions");
|
||||
debug!("Managing turbo in auto mode based on system conditions");
|
||||
manage_auto_turbo(report, selected_profile_config)?;
|
||||
}
|
||||
_ => cpu::set_turbo(turbo_setting)?,
|
||||
|
@ -70,31 +68,31 @@ pub fn determine_and_apply_settings(
|
|||
}
|
||||
|
||||
if let Some(epp) = &selected_profile_config.epp {
|
||||
println!("Engine: Setting EPP to '{epp}'");
|
||||
info!("Setting EPP to '{epp}'");
|
||||
cpu::set_epp(epp, None)?;
|
||||
}
|
||||
|
||||
if let Some(epb) = &selected_profile_config.epb {
|
||||
println!("Engine: Setting EPB to '{epb}'");
|
||||
info!("Setting EPB to '{epb}'");
|
||||
cpu::set_epb(epb, None)?;
|
||||
}
|
||||
|
||||
if let Some(min_freq) = selected_profile_config.min_freq_mhz {
|
||||
println!("Engine: Setting min frequency to '{min_freq} MHz'");
|
||||
info!("Setting min frequency to '{min_freq} MHz'");
|
||||
cpu::set_min_frequency(min_freq, None)?;
|
||||
}
|
||||
|
||||
if let Some(max_freq) = selected_profile_config.max_freq_mhz {
|
||||
println!("Engine: Setting max frequency to '{max_freq} MHz'");
|
||||
info!("Setting max frequency to '{max_freq} MHz'");
|
||||
cpu::set_max_frequency(max_freq, None)?;
|
||||
}
|
||||
|
||||
if let Some(profile) = &selected_profile_config.platform_profile {
|
||||
println!("Engine: Setting platform profile to '{profile}'");
|
||||
info!("Setting platform profile to '{profile}'");
|
||||
cpu::set_platform_profile(profile)?;
|
||||
}
|
||||
|
||||
println!("Engine: Profile settings applied successfully.");
|
||||
debug!("Profile settings applied successfully.");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -140,24 +138,24 @@ fn manage_auto_turbo(report: &SystemReport, config: &ProfileConfig) -> Result<()
|
|||
let enable_turbo = match (cpu_temp, avg_cpu_usage) {
|
||||
// If temperature is too high, disable turbo regardless of load
|
||||
(Some(temp), _) if temp >= turbo_settings.temp_threshold_high => {
|
||||
println!(
|
||||
"Engine: Auto Turbo: Disabled due to high temperature ({:.1}°C >= {:.1}°C)",
|
||||
info!(
|
||||
"Auto Turbo: Disabled due to high temperature ({:.1}°C >= {:.1}°C)",
|
||||
temp, turbo_settings.temp_threshold_high
|
||||
);
|
||||
false
|
||||
}
|
||||
// If load is high enough, enable turbo (unless temp already caused it to disable)
|
||||
(_, Some(usage)) if usage >= turbo_settings.load_threshold_high => {
|
||||
println!(
|
||||
"Engine: Auto Turbo: Enabled due to high CPU load ({:.1}% >= {:.1}%)",
|
||||
info!(
|
||||
"Auto Turbo: Enabled due to high CPU load ({:.1}% >= {:.1}%)",
|
||||
usage, turbo_settings.load_threshold_high
|
||||
);
|
||||
true
|
||||
}
|
||||
// If load is low, disable turbo
|
||||
(_, Some(usage)) if usage <= turbo_settings.load_threshold_low => {
|
||||
println!(
|
||||
"Engine: Auto Turbo: Disabled due to low CPU load ({:.1}% <= {:.1}%)",
|
||||
info!(
|
||||
"Auto Turbo: Disabled due to low CPU load ({:.1}% <= {:.1}%)",
|
||||
usage, turbo_settings.load_threshold_low
|
||||
);
|
||||
false
|
||||
|
@ -165,7 +163,7 @@ fn manage_auto_turbo(report: &SystemReport, config: &ProfileConfig) -> Result<()
|
|||
// In intermediate load scenarios or if we can't determine, leave turbo in current state
|
||||
// For now, we'll disable it as a safe default
|
||||
_ => {
|
||||
println!("Engine: Auto Turbo: Disabled (default for indeterminate state)");
|
||||
info!("Auto Turbo: Disabled (default for indeterminate state)");
|
||||
false
|
||||
}
|
||||
};
|
||||
|
@ -179,8 +177,8 @@ fn manage_auto_turbo(report: &SystemReport, config: &ProfileConfig) -> Result<()
|
|||
|
||||
match cpu::set_turbo(turbo_setting) {
|
||||
Ok(()) => {
|
||||
println!(
|
||||
"Engine: Auto Turbo: Successfully set turbo to {}",
|
||||
debug!(
|
||||
"Auto Turbo: Successfully set turbo to {}",
|
||||
if enable_turbo { "enabled" } else { "disabled" }
|
||||
);
|
||||
Ok(())
|
||||
|
|
55
src/main.rs
55
src/main.rs
|
@ -12,6 +12,9 @@ use crate::config::AppConfig;
|
|||
use crate::core::{GovernorOverrideMode, TurboSetting};
|
||||
use crate::util::error::ControlError;
|
||||
use clap::Parser;
|
||||
use env_logger::Builder;
|
||||
use log::{debug, error, info};
|
||||
use std::sync::Once;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
|
@ -77,6 +80,9 @@ enum Commands {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
// Initialize logger once for the entire application
|
||||
init_logger();
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
// Load configuration first, as it might be needed by the monitor module
|
||||
|
@ -84,7 +90,7 @@ fn main() {
|
|||
let config = match config::load_config() {
|
||||
Ok(cfg) => cfg,
|
||||
Err(e) => {
|
||||
eprintln!("Error loading configuration: {e}. Using default values.");
|
||||
error!("Error loading configuration: {e}. Using default values.");
|
||||
// Proceed with default config if loading fails, as per previous steps
|
||||
AppConfig::default()
|
||||
}
|
||||
|
@ -100,12 +106,12 @@ fn main() {
|
|||
let total_width = title_len + 8; // 8 is for padding (4 on each side)
|
||||
let separator = "═".repeat(total_width);
|
||||
|
||||
println!("\n╔{}╗", separator);
|
||||
println!("\n╔{separator}╗");
|
||||
|
||||
// Calculate centering
|
||||
println!("║ {} ║", title);
|
||||
println!("║ {title} ║");
|
||||
|
||||
println!("╚{}╝", separator);
|
||||
println!("╚{separator}╝");
|
||||
};
|
||||
|
||||
format_section("System Information");
|
||||
|
@ -164,7 +170,7 @@ fn main() {
|
|||
"CPU Temperature: {}",
|
||||
report.cpu_global.average_temperature_celsius.map_or_else(
|
||||
|| "N/A (No sensor detected)".to_string(),
|
||||
|t| format!("{:.1}°C", t)
|
||||
|t| format!("{t:.1}°C")
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -205,9 +211,9 @@ fn main() {
|
|||
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)
|
||||
format!("{freq}*")
|
||||
} else {
|
||||
format!("{}", freq)
|
||||
format!("{freq}")
|
||||
}
|
||||
}
|
||||
None => "N/A".to_string(),
|
||||
|
@ -234,13 +240,13 @@ fn main() {
|
|||
"{}%",
|
||||
core_info
|
||||
.usage_percent
|
||||
.map_or_else(|| "N/A".to_string(), |f| format!("{:.1}", f))
|
||||
.map_or_else(|| "N/A".to_string(), |f| format!("{f:.1}"))
|
||||
),
|
||||
format!(
|
||||
"{}°C",
|
||||
core_info
|
||||
.temperature_celsius
|
||||
.map_or_else(|| "N/A".to_string(), |f| format!("{:.1}", f))
|
||||
.map_or_else(|| "N/A".to_string(), |f| format!("{f:.1}"))
|
||||
),
|
||||
width = max_core_id_len
|
||||
);
|
||||
|
@ -355,24 +361,24 @@ fn main() {
|
|||
Some(Commands::Daemon { verbose }) => daemon::run_daemon(config, verbose),
|
||||
Some(Commands::Debug) => cli::debug::run_debug(&config),
|
||||
None => {
|
||||
println!("Welcome to superfreq! Use --help for commands.");
|
||||
println!("Current effective configuration: {config:?}");
|
||||
info!("Welcome to superfreq! Use --help for commands.");
|
||||
debug!("Current effective configuration: {config:?}");
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(e) = command_result {
|
||||
eprintln!("Error executing command: {e}");
|
||||
error!("Error executing command: {e}");
|
||||
if let Some(source) = e.source() {
|
||||
eprintln!("Caused by: {source}");
|
||||
error!("Caused by: {source}");
|
||||
}
|
||||
// TODO: Consider specific error handling for PermissionDenied from cpu here
|
||||
// For example, check if e.downcast_ref::<cpu::ControlError>() matches PermissionDenied
|
||||
// TODO: Consider specific error handling for PermissionDenied from the cpu module here.
|
||||
// For example, check if `e.downcast_ref::<cpu::ControlError>()` matches `PermissionDenied`
|
||||
// and print a more specific message like "Try running with sudo."
|
||||
// We'll revisit this in the future once CPU logic is more stable.
|
||||
if let Some(control_error) = e.downcast_ref::<ControlError>() {
|
||||
if matches!(control_error, ControlError::PermissionDenied(_)) {
|
||||
eprintln!(
|
||||
error!(
|
||||
"Hint: This operation may require administrator privileges (e.g., run with sudo)."
|
||||
);
|
||||
}
|
||||
|
@ -381,3 +387,20 @@ fn main() {
|
|||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize the logger for the entire application
|
||||
static LOGGER_INIT: Once = Once::new();
|
||||
fn init_logger() {
|
||||
LOGGER_INIT.call_once(|| {
|
||||
// Set default log level based on environment or default to Info
|
||||
let env_log = std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string());
|
||||
|
||||
Builder::new()
|
||||
.parse_filters(&env_log)
|
||||
.format_timestamp(None)
|
||||
.format_module_path(false)
|
||||
.init();
|
||||
|
||||
debug!("Logger initialized with RUST_LOG={env_log}");
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue