diff --git a/agent/src/collectors/service.rs b/agent/src/collectors/service.rs index 2c68839..074c006 100644 --- a/agent/src/collectors/service.rs +++ b/agent/src/collectors/service.rs @@ -98,6 +98,13 @@ impl ServiceCollector { 0.0 }; + // Get disk quota for this service (if configured) + let disk_quota_gb = if matches!(status, ServiceStatus::Running) { + self.get_service_disk_quota(service).await.unwrap_or(0.0) + } else { + 0.0 + }; + // Get service-specific description (only for running services) let description = if matches!(status, ServiceStatus::Running) { self.get_service_description_with_cache(service).await @@ -113,7 +120,7 @@ impl ServiceCollector { cpu_percent, sandbox_limit: None, // TODO: Implement sandbox limit detection disk_used_gb, - disk_quota_gb: 0.0, // Will be set to system total in collect() + disk_quota_gb, description, sub_service: None, }) @@ -258,6 +265,80 @@ impl ServiceCollector { Ok(0.0) } + async fn get_service_disk_quota(&self, service: &str) -> Result { + // Check systemd for disk-related limits (limited options available) + // Most systemd services don't have disk quotas, but we can check for some storage-related settings + + // Check for filesystem quotas on service data directories + let service_paths = vec![ + format!("/var/lib/{}", service), + format!("/opt/{}", service), + format!("/srv/{}", service), + ]; + + for path in &service_paths { + if tokio::fs::metadata(path).await.is_ok() { + // Try quota command (if available) + if let Ok(quota_gb) = self.check_filesystem_quota(path).await { + if quota_gb > 0.0 { + return Ok(quota_gb); + } + } + } + } + + // Service-specific quota detection + match service { + "docker" => { + // Docker might have storage driver limits + if let Ok(limit) = self.get_docker_storage_quota().await { + return Ok(limit); + } + }, + _ => {} + } + + // No quota found + Err(CollectorError::ParseError { + message: format!("No disk quota found for service {}", service), + }) + } + + async fn check_filesystem_quota(&self, path: &str) -> Result { + // Try to get filesystem quota information + let quota_output = Command::new("quota") + .args(["-f", path]) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output() + .await; + + if let Ok(output) = quota_output { + if output.status.success() { + let stdout = String::from_utf8_lossy(&output.stdout); + // Parse quota output (simplified implementation) + for line in stdout.lines() { + if line.contains("blocks") && line.contains("quota") { + // This would need proper parsing based on quota output format + // For now, return error indicating no quota parsing implemented + } + } + } + } + + Err(CollectorError::ParseError { + message: "No filesystem quota detected".to_string(), + }) + } + + async fn get_docker_storage_quota(&self) -> Result { + // Check if Docker has storage limits configured + // This is a simplified check - full implementation would check storage driver settings + Err(CollectorError::ParseError { + message: "Docker storage quota detection not implemented".to_string(), + }) + } + async fn get_service_memory_limit(&self, service: &str) -> Result { let output = Command::new("/run/current-system/sw/bin/systemctl") .args(["show", service, "--property=MemoryMax", "--no-pager"]) @@ -1209,19 +1290,8 @@ impl Collector for ServiceCollector { used_gb: 0.0, }); - // Get system memory total for services without memory quotas - let system_memory_total_mb = self.get_system_memory_total().await.unwrap_or(8192.0); // Default 8GB - - // Set quotas to system totals for services that don't have specific quotas - let system_disk_capacity_gb = disk_usage.total_capacity_gb; - for service in &mut services { - if service.disk_quota_gb == 0.0 { - service.disk_quota_gb = system_disk_capacity_gb; - } - if service.memory_quota_mb == 0.0 { - service.memory_quota_mb = system_memory_total_mb; - } - } + // Memory quotas remain as detected from systemd - don't default to system total + // Services without memory limits will show quota = 0.0 and display usage only // Calculate overall services status let services_status = self.determine_services_status(healthy, degraded, failed); diff --git a/dashboard/src/ui/services.rs b/dashboard/src/ui/services.rs index 2808caa..01f1189 100644 --- a/dashboard/src/ui/services.rs +++ b/dashboard/src/ui/services.rs @@ -141,6 +141,7 @@ fn format_memory_value(used: f32, quota: f32) -> String { let used_gb = used / 1000.0; let quota_gb = quota / 1000.0; + // Show usage/quota format only if quota exists, otherwise just usage if quota > 0.05 { format!("{:.1}/{:.1}", used_gb, quota_gb) } else if used > 0.05 { @@ -159,7 +160,11 @@ fn format_cpu_value(cpu_percent: f32) -> String { } fn format_disk_value(used: f32, quota: f32) -> String { - // Always show in GB format with usage/quota, no units (units in column header) - format!("{:.1}/{:.1}", used, quota) + // Show usage/quota format only if quota exists, otherwise just usage + if quota > 0.05 { + format!("{:.1}/{:.1}", used, quota) + } else { + format!("{:.1}", used) + } }