use serde::{Deserialize, Serialize};
use tacet_core::result::{PreflightCategory, PreflightSeverity, PreflightWarningInfo};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SystemWarning {
CpuGovernorNotPerformance {
current: String,
recommended: String,
},
CpuGovernorUnreadable {
reason: String,
},
TurboBoostEnabled,
HyperthreadingEnabled,
VirtualMachineDetected {
vm_type: Option<String>,
},
HighSystemLoad {
load_average: f64,
threshold: f64,
},
}
impl SystemWarning {
pub fn is_result_undermining(&self) -> bool {
false
}
#[deprecated(note = "Use is_result_undermining() instead")]
pub fn is_critical(&self) -> bool {
false
}
pub fn severity(&self) -> PreflightSeverity {
PreflightSeverity::Informational
}
pub fn description(&self) -> String {
match self {
SystemWarning::CpuGovernorNotPerformance {
current,
recommended,
} => {
format!(
"CPU governor is '{}', recommend '{}'.",
current, recommended
)
}
SystemWarning::CpuGovernorUnreadable { reason } => {
format!("Could not check CPU governor: {}.", reason)
}
SystemWarning::TurboBoostEnabled => {
"Turbo boost enabled - can cause timing variability.".to_string()
}
SystemWarning::HyperthreadingEnabled => {
"Hyperthreading detected - consider pinning to physical cores.".to_string()
}
SystemWarning::VirtualMachineDetected { vm_type } => {
let vm_info = vm_type
.as_ref()
.map(|t| format!(" ({})", t))
.unwrap_or_default();
format!(
"Running in a virtual machine{}. Timing measurements may be less reliable.",
vm_info
)
}
SystemWarning::HighSystemLoad {
load_average,
threshold,
} => {
format!(
"High system load: {:.1} (threshold: {:.1}).",
load_average, threshold
)
}
}
}
pub fn guidance(&self) -> Option<String> {
match self {
SystemWarning::CpuGovernorNotPerformance { .. } => {
Some("Set with: sudo cpufreq-set -g performance".to_string())
}
SystemWarning::CpuGovernorUnreadable { .. } => None,
SystemWarning::TurboBoostEnabled => {
Some("Consider disabling for more stable measurements.".to_string())
}
SystemWarning::HyperthreadingEnabled => {
Some("Pin to physical cores for more stable timing.".to_string())
}
SystemWarning::VirtualMachineDetected { .. } => {
Some("Consider running on bare metal for more reliable measurements.".to_string())
}
SystemWarning::HighSystemLoad { .. } => {
Some("Reduce background processes for more stable measurements.".to_string())
}
}
}
pub fn to_warning_info(&self) -> PreflightWarningInfo {
match self.guidance() {
Some(guidance) => PreflightWarningInfo::with_guidance(
PreflightCategory::System,
self.severity(),
self.description(),
guidance,
),
None => PreflightWarningInfo::new(
PreflightCategory::System,
self.severity(),
self.description(),
),
}
}
}
pub fn system_check() -> Vec<SystemWarning> {
#[allow(unused_mut)]
let mut warnings = Vec::new();
#[cfg(target_os = "linux")]
{
if let Some(warning) = check_cpu_governor_linux() {
warnings.push(warning);
}
if let Some(warning) = check_turbo_boost_linux() {
warnings.push(warning);
}
if let Some(warning) = check_hyperthreading_linux() {
warnings.push(warning);
}
if let Some(warning) = check_vm_detection_linux() {
warnings.push(warning);
}
if let Some(warning) = check_load_linux() {
warnings.push(warning);
}
}
#[cfg(target_os = "macos")]
{
let _ = check_macos_power_settings();
}
#[cfg(target_os = "windows")]
{
let _ = check_windows_power_settings();
}
warnings
}
#[cfg(target_os = "linux")]
fn check_cpu_governor_linux() -> Option<SystemWarning> {
let governor_paths = [
"/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor",
"/sys/devices/system/cpu/cpufreq/policy0/scaling_governor",
];
for path in &governor_paths {
match std::fs::read_to_string(path) {
Ok(governor) => {
let governor = governor.trim().to_lowercase();
if governor != "performance" {
return Some(SystemWarning::CpuGovernorNotPerformance {
current: governor,
recommended: "performance".to_string(),
});
} else {
return None; }
}
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
continue;
}
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
return Some(SystemWarning::CpuGovernorUnreadable {
reason: format!("Permission denied reading {}", path),
});
}
Err(_) => {
continue;
}
}
}
None
}
#[cfg(target_os = "macos")]
fn check_macos_power_settings() -> Option<SystemWarning> {
None
}
#[cfg(target_os = "windows")]
fn check_windows_power_settings() -> Option<SystemWarning> {
None
}
#[cfg(target_os = "linux")]
fn check_turbo_boost_linux() -> Option<SystemWarning> {
let intel_path = "/sys/devices/system/cpu/intel_pstate/no_turbo";
if let Ok(value) = std::fs::read_to_string(intel_path) {
if value.trim() == "0" {
return Some(SystemWarning::TurboBoostEnabled);
}
return None;
}
let generic_path = "/sys/devices/system/cpu/cpufreq/boost";
if let Ok(value) = std::fs::read_to_string(generic_path) {
if value.trim() == "1" {
return Some(SystemWarning::TurboBoostEnabled);
}
}
None
}
#[cfg(target_os = "linux")]
fn check_hyperthreading_linux() -> Option<SystemWarning> {
let path = "/sys/devices/system/cpu/smt/active";
if let Ok(value) = std::fs::read_to_string(path) {
if value.trim() == "1" {
return Some(SystemWarning::HyperthreadingEnabled);
}
}
None
}
#[cfg(target_os = "linux")]
fn check_vm_detection_linux() -> Option<SystemWarning> {
let cpuinfo = std::fs::read_to_string("/proc/cpuinfo").ok()?;
if cpuinfo.to_lowercase().contains("hypervisor") {
return Some(SystemWarning::VirtualMachineDetected { vm_type: None });
}
None
}
#[cfg(target_os = "linux")]
fn check_load_linux() -> Option<SystemWarning> {
let loadavg = std::fs::read_to_string("/proc/loadavg").ok()?;
let load = loadavg
.split_whitespace()
.next()
.and_then(|val| val.parse::<f64>().ok())?;
let threshold = 1.0;
if load > threshold {
Some(SystemWarning::HighSystemLoad {
load_average: load,
threshold,
})
} else {
None
}
}
#[allow(dead_code)]
fn check_system_load() -> Option<SystemWarning> {
const LOAD_THRESHOLD: f64 = 1.0;
let _ = LOAD_THRESHOLD;
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_system_check_runs() {
let _warnings = system_check();
}
#[test]
fn test_warning_descriptions() {
let warning = SystemWarning::CpuGovernorNotPerformance {
current: "powersave".to_string(),
recommended: "performance".to_string(),
};
let desc = warning.description();
assert!(desc.contains("powersave"));
assert!(desc.contains("performance"));
let warning = SystemWarning::TurboBoostEnabled;
let desc = warning.description();
assert!(desc.contains("Turbo boost"));
let warning = SystemWarning::VirtualMachineDetected {
vm_type: Some("QEMU".to_string()),
};
let desc = warning.description();
assert!(desc.contains("virtual machine"));
assert!(desc.contains("QEMU"));
let warning = SystemWarning::HighSystemLoad {
load_average: 2.5,
threshold: 1.0,
};
let desc = warning.description();
assert!(desc.contains("2.5"));
}
#[test]
fn test_warning_is_not_critical() {
let warnings = vec![
SystemWarning::CpuGovernorNotPerformance {
current: "powersave".to_string(),
recommended: "performance".to_string(),
},
SystemWarning::TurboBoostEnabled,
SystemWarning::HyperthreadingEnabled,
SystemWarning::VirtualMachineDetected { vm_type: None },
SystemWarning::HighSystemLoad {
load_average: 2.0,
threshold: 1.0,
},
];
for warning in warnings {
assert!(
!warning.is_result_undermining(),
"System warnings should not undermine results"
);
assert_eq!(warning.severity(), PreflightSeverity::Informational);
}
}
#[test]
fn test_severity() {
let governor = SystemWarning::CpuGovernorNotPerformance {
current: "powersave".to_string(),
recommended: "performance".to_string(),
};
assert_eq!(governor.severity(), PreflightSeverity::Informational);
assert!(!governor.is_result_undermining());
}
}