Restore service discovery and disk usage calculation
Some checks failed
Build and Release / build-and-release (push) Failing after 1m2s
Some checks failed
Build and Release / build-and-release (push) Failing after 1m2s
Fixes missing services and 0B disk usage issues by restoring: - Wildcard pattern matching for service filters (gitea*, redis*) - Service disk usage calculation from directories and WorkingDirectory - Proper Status::Inactive for inactive services Services now properly discovered and show actual disk usage.
This commit is contained in:
parent
66ab7a492d
commit
b120f95f8a
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "cm-dashboard-agent"
|
||||
version = "0.1.141"
|
||||
version = "0.1.142"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use cm_dashboard_shared::{AgentData, ServiceData};
|
||||
use cm_dashboard_shared::{AgentData, ServiceData, Status};
|
||||
use std::process::Command;
|
||||
use std::sync::RwLock;
|
||||
use std::time::Instant;
|
||||
@ -66,11 +66,12 @@ impl SystemdCollector {
|
||||
// Populate AgentData with service information
|
||||
for service in services {
|
||||
agent_data.services.push(ServiceData {
|
||||
name: service.name,
|
||||
status: service.status,
|
||||
name: service.name.clone(),
|
||||
status: service.status.clone(),
|
||||
memory_mb: service.memory_mb,
|
||||
disk_gb: service.disk_gb,
|
||||
user_stopped: false, // TODO: Integrate with service tracker
|
||||
service_status: self.calculate_service_status(&service.name, &service.status),
|
||||
});
|
||||
}
|
||||
|
||||
@ -113,16 +114,20 @@ impl SystemdCollector {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filter services based on configuration
|
||||
if self.config.service_name_filters.is_empty() || self.config.service_name_filters.contains(&service_name.to_string()) {
|
||||
// Filter services based on configuration with wildcard support
|
||||
if self.should_monitor_service(service_name) {
|
||||
// Get memory usage for this service
|
||||
let memory_mb = self.get_service_memory_usage(service_name).await.unwrap_or(0.0);
|
||||
|
||||
// Get disk usage for this service
|
||||
let disk_gb = self.get_service_disk_usage(service_name).await.unwrap_or(0.0);
|
||||
|
||||
let normalized_status = self.normalize_service_status(active_state, sub_state);
|
||||
let service_info = ServiceInfo {
|
||||
name: service_name.to_string(),
|
||||
status: self.normalize_service_status(active_state, sub_state),
|
||||
status: normalized_status,
|
||||
memory_mb,
|
||||
disk_gb: 0.0, // Services typically don't have disk usage
|
||||
disk_gb,
|
||||
};
|
||||
|
||||
services.push(service_info);
|
||||
@ -133,6 +138,108 @@ impl SystemdCollector {
|
||||
Ok(services)
|
||||
}
|
||||
|
||||
/// Check if a service should be monitored based on configuration filters with wildcard support
|
||||
fn should_monitor_service(&self, service_name: &str) -> bool {
|
||||
// If no filters configured, monitor nothing (to prevent noise)
|
||||
if self.config.service_name_filters.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if service matches any of the configured patterns
|
||||
for pattern in &self.config.service_name_filters {
|
||||
if self.matches_pattern(service_name, pattern) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// Check if service name matches pattern (supports wildcards like nginx*)
|
||||
fn matches_pattern(&self, service_name: &str, pattern: &str) -> bool {
|
||||
if pattern.ends_with('*') {
|
||||
let prefix = &pattern[..pattern.len() - 1];
|
||||
service_name.starts_with(prefix)
|
||||
} else {
|
||||
service_name == pattern
|
||||
}
|
||||
}
|
||||
|
||||
/// Get disk usage for a specific service
|
||||
async fn get_service_disk_usage(&self, service_name: &str) -> Result<f32, CollectorError> {
|
||||
// Check if this service has configured directory paths
|
||||
if let Some(dirs) = self.config.service_directories.get(service_name) {
|
||||
// Service has configured paths - use the first accessible one
|
||||
for dir in dirs {
|
||||
if let Some(size) = self.get_directory_size(dir) {
|
||||
return Ok(size);
|
||||
}
|
||||
}
|
||||
// If configured paths failed, return 0
|
||||
return Ok(0.0);
|
||||
}
|
||||
|
||||
// No configured path - try to get WorkingDirectory from systemctl
|
||||
let output = Command::new("systemctl")
|
||||
.args(&["show", &format!("{}.service", service_name), "--property=WorkingDirectory"])
|
||||
.output()
|
||||
.map_err(|e| CollectorError::SystemRead {
|
||||
path: format!("WorkingDirectory for {}", service_name),
|
||||
error: e.to_string(),
|
||||
})?;
|
||||
|
||||
let output_str = String::from_utf8_lossy(&output.stdout);
|
||||
for line in output_str.lines() {
|
||||
if line.starts_with("WorkingDirectory=") && !line.contains("[not set]") {
|
||||
let dir = line.strip_prefix("WorkingDirectory=").unwrap_or("");
|
||||
if !dir.is_empty() {
|
||||
return Ok(self.get_directory_size(dir).unwrap_or(0.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(0.0)
|
||||
}
|
||||
|
||||
/// Get size of a directory in GB
|
||||
fn get_directory_size(&self, path: &str) -> Option<f32> {
|
||||
let output = Command::new("du")
|
||||
.args(&["-sb", path])
|
||||
.output()
|
||||
.ok()?;
|
||||
|
||||
if !output.status.success() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let output_str = String::from_utf8_lossy(&output.stdout);
|
||||
let parts: Vec<&str> = output_str.split_whitespace().collect();
|
||||
if let Some(size_str) = parts.first() {
|
||||
if let Ok(size_bytes) = size_str.parse::<u64>() {
|
||||
return Some(size_bytes as f32 / (1024.0 * 1024.0 * 1024.0));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Calculate service status, taking user-stopped services into account
|
||||
fn calculate_service_status(&self, service_name: &str, active_status: &str) -> Status {
|
||||
match active_status.to_lowercase().as_str() {
|
||||
"active" => Status::Ok,
|
||||
"inactive" | "dead" => {
|
||||
debug!("Service '{}' is inactive - treating as Inactive status", service_name);
|
||||
Status::Inactive
|
||||
},
|
||||
"failed" | "error" => Status::Critical,
|
||||
"activating" | "deactivating" | "reloading" | "starting" | "stopping" => {
|
||||
debug!("Service '{}' is transitioning - treating as Pending", service_name);
|
||||
Status::Pending
|
||||
},
|
||||
_ => Status::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get memory usage for a specific service
|
||||
async fn get_service_memory_usage(&self, service_name: &str) -> Result<f32, CollectorError> {
|
||||
let output = Command::new("systemctl")
|
||||
@ -206,11 +313,12 @@ impl Collector for SystemdCollector {
|
||||
debug!("Using cached systemd services data");
|
||||
for service in cached_services {
|
||||
agent_data.services.push(ServiceData {
|
||||
name: service.name,
|
||||
status: service.status,
|
||||
name: service.name.clone(),
|
||||
status: service.status.clone(),
|
||||
memory_mb: service.memory_mb,
|
||||
disk_gb: service.disk_gb,
|
||||
user_stopped: false, // TODO: Integrate with service tracker
|
||||
service_status: self.calculate_service_status(&service.name, &service.status),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "cm-dashboard"
|
||||
version = "0.1.141"
|
||||
version = "0.1.142"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "cm-dashboard-shared"
|
||||
version = "0.1.141"
|
||||
version = "0.1.142"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user