This commit is contained in:
2025-10-12 14:53:27 +02:00
parent 2581435b10
commit 2239badc8a
16 changed files with 1116 additions and 1414 deletions

View File

@@ -82,7 +82,7 @@ impl ServiceCollector {
// Get memory quota from systemd if available
let memory_quota_mb = self.get_service_memory_limit(service).await.unwrap_or(0.0);
// Get disk usage for this service
let disk_used_gb = self.get_service_disk_usage(service).await.unwrap_or(0.0);
@@ -149,7 +149,7 @@ impl ServiceCollector {
async fn get_service_disk_usage(&self, service: &str) -> Result<f32, CollectorError> {
// For systemd services, check if they have private /var directories or specific data paths
// This is a simplified implementation - could be enhanced to check actual service-specific paths
// Common service data directories to check
let potential_paths = vec![
format!("/var/lib/{}", service),
@@ -158,21 +158,21 @@ impl ServiceCollector {
format!("/opt/{}", service),
format!("/srv/{}", service),
];
let mut total_usage = 0.0;
for path in potential_paths {
if let Ok(usage) = self.get_directory_size(&path).await {
total_usage += usage;
}
}
Ok(total_usage)
}
async fn get_directory_size(&self, path: &str) -> Result<f32, CollectorError> {
let output = Command::new("du")
.args(["-s", "-k", path]) // Use kilobytes instead of forcing GB
.args(["-s", "-k", path]) // Use kilobytes instead of forcing GB
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
@@ -195,7 +195,7 @@ impl ServiceCollector {
return Ok(size_gb);
}
}
Ok(0.0)
}

View File

@@ -89,7 +89,10 @@ impl SmartCollector {
Ok(SmartDeviceData::from_smartctl_output(device, smart_output))
}
async fn get_drive_usage(&self, device: &str) -> Result<(Option<f32>, Option<f32>), CollectorError> {
async fn get_drive_usage(
&self,
device: &str,
) -> Result<(Option<f32>, Option<f32>), CollectorError> {
// Get capacity first
let capacity = match self.get_drive_capacity(device).await {
Ok(cap) => Some(cap),
@@ -134,8 +137,8 @@ impl SmartCollector {
}
let stdout = String::from_utf8_lossy(&output.stdout);
let lsblk_output: serde_json::Value = serde_json::from_str(&stdout)
.map_err(|e| CollectorError::ParseError {
let lsblk_output: serde_json::Value =
serde_json::from_str(&stdout).map_err(|e| CollectorError::ParseError {
message: format!("Failed to parse lsblk JSON: {}", e),
})?;
@@ -155,25 +158,28 @@ impl SmartCollector {
fn parse_lsblk_size(&self, size_str: &str) -> Result<f32, CollectorError> {
// Parse sizes like "953,9G", "1T", "512M"
let size_str = size_str.replace(',', "."); // Handle European decimal separator
let size_str = size_str.replace(',', "."); // Handle European decimal separator
if let Some(pos) = size_str.find(|c: char| c.is_alphabetic()) {
let (number_part, unit_part) = size_str.split_at(pos);
let number: f32 = number_part.parse()
let number: f32 = number_part
.parse()
.map_err(|e| CollectorError::ParseError {
message: format!("Failed to parse size number '{}': {}", number_part, e),
})?;
let multiplier = match unit_part.to_uppercase().as_str() {
"T" | "TB" => 1024.0,
"G" | "GB" => 1.0,
"M" | "MB" => 1.0 / 1024.0,
"K" | "KB" => 1.0 / (1024.0 * 1024.0),
_ => return Err(CollectorError::ParseError {
message: format!("Unknown size unit: {}", unit_part),
}),
_ => {
return Err(CollectorError::ParseError {
message: format!("Unknown size unit: {}", unit_part),
})
}
};
Ok(number * multiplier)
} else {
Err(CollectorError::ParseError {
@@ -428,18 +434,18 @@ mod tests {
#[test]
fn test_parse_lsblk_size() {
let collector = SmartCollector::new(true, 5000, vec![]);
// Test gigabyte sizes
assert!((collector.parse_lsblk_size("953,9G").unwrap() - 953.9).abs() < 0.1);
assert!((collector.parse_lsblk_size("1G").unwrap() - 1.0).abs() < 0.1);
// Test terabyte sizes
assert!((collector.parse_lsblk_size("1T").unwrap() - 1024.0).abs() < 0.1);
assert!((collector.parse_lsblk_size("2,5T").unwrap() - 2560.0).abs() < 0.1);
// Test megabyte sizes
assert!((collector.parse_lsblk_size("512M").unwrap() - 0.5).abs() < 0.1);
// Test error cases
assert!(collector.parse_lsblk_size("invalid").is_err());
assert!(collector.parse_lsblk_size("1X").is_err());