diff --git a/agent/src/collectors/disk.rs b/agent/src/collectors/disk.rs index 649400a..8eaefbb 100644 --- a/agent/src/collectors/disk.rs +++ b/agent/src/collectors/disk.rs @@ -219,18 +219,12 @@ impl DiskCollector { } /// Parse wear level from SMART output (SSD wear leveling) + /// Supports both NVMe and SATA SSD wear indicators fn parse_wear_level_from_smart(&self, smart_output: &str) -> Option { for line in smart_output.lines() { - // Look for wear leveling indicators - if line.contains("Wear_Leveling_Count") || line.contains("Media_Wearout_Indicator") { - let parts: Vec<&str> = line.split_whitespace().collect(); - if parts.len() >= 10 { - if let Ok(wear) = parts[9].parse::() { - return Some(100.0 - wear); // Convert to percentage used - } - } - } - // NVMe drives might show percentage used directly + let line = line.trim(); + + // NVMe drives - direct percentage used if line.contains("Percentage Used:") { if let Some(wear_part) = line.split("Percentage Used:").nth(1) { if let Some(wear_str) = wear_part.split('%').next() { @@ -240,6 +234,38 @@ impl DiskCollector { } } } + + // SATA SSD attributes - parse SMART table format + // Format: ID ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.len() >= 10 { + // SSD Life Left / Percent Lifetime Remaining (higher = less wear) + if line.contains("SSD_Life_Left") || line.contains("Percent_Lifetime_Remain") { + if let Ok(remaining) = parts[3].parse::() { // VALUE column + return Some(100.0 - remaining); // Convert remaining to used + } + } + + // Media Wearout Indicator (lower = more wear, normalize to 0-100) + if line.contains("Media_Wearout_Indicator") { + if let Ok(remaining) = parts[3].parse::() { // VALUE column + return Some(100.0 - remaining); // Convert remaining to used + } + } + + // Wear Leveling Count (higher = less wear, but varies by manufacturer) + if line.contains("Wear_Leveling_Count") { + if let Ok(wear_count) = parts[3].parse::() { // VALUE column + // Most SSDs: 100 = new, decreases with wear + if wear_count <= 100.0 { + return Some(100.0 - wear_count); + } + } + } + + // Total LBAs Written - calculate against typical endurance if available + // This is more complex and manufacturer-specific, so we skip for now + } } None }