Fix nginx sub-services persistent caching with complete service data storage
All checks were successful
Build and Release / build-and-release (push) Successful in 1m17s
All checks were successful
Build and Release / build-and-release (push) Successful in 1m17s
Resolves nginx sites appearing only briefly during collection cycles by implementing proper caching of complete service data including sub-services. Changes: - Add cached_service_data field to store complete ServiceData with sub-services - Modify collection logic to cache full service objects instead of basic ServiceInfo - Update cache retrieval to use complete cached data preserving nginx site metrics - Eliminate flickering of nginx sites between collection cycles Version bump to v0.1.148
This commit is contained in:
parent
7f26991609
commit
d89b3ac881
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -279,7 +279,7 @@ checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cm-dashboard"
|
name = "cm-dashboard"
|
||||||
version = "0.1.146"
|
version = "0.1.147"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -301,7 +301,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cm-dashboard-agent"
|
name = "cm-dashboard-agent"
|
||||||
version = "0.1.146"
|
version = "0.1.147"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -324,7 +324,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cm-dashboard-shared"
|
name = "cm-dashboard-shared"
|
||||||
version = "0.1.146"
|
version = "0.1.147"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cm-dashboard-agent"
|
name = "cm-dashboard-agent"
|
||||||
version = "0.1.147"
|
version = "0.1.148"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -24,6 +24,8 @@ struct ServiceCacheState {
|
|||||||
last_collection: Option<Instant>,
|
last_collection: Option<Instant>,
|
||||||
/// Cached service data
|
/// Cached service data
|
||||||
services: Vec<ServiceInfo>,
|
services: Vec<ServiceInfo>,
|
||||||
|
/// Cached complete service data with sub-services
|
||||||
|
cached_service_data: Vec<ServiceData>,
|
||||||
/// Interesting services to monitor (cached after discovery)
|
/// Interesting services to monitor (cached after discovery)
|
||||||
monitored_services: Vec<String>,
|
monitored_services: Vec<String>,
|
||||||
/// Cached service status information from discovery
|
/// Cached service status information from discovery
|
||||||
@ -62,6 +64,7 @@ impl SystemdCollector {
|
|||||||
let state = ServiceCacheState {
|
let state = ServiceCacheState {
|
||||||
last_collection: None,
|
last_collection: None,
|
||||||
services: Vec::new(),
|
services: Vec::new(),
|
||||||
|
cached_service_data: Vec::new(),
|
||||||
monitored_services: Vec::new(),
|
monitored_services: Vec::new(),
|
||||||
service_status_cache: std::collections::HashMap::new(),
|
service_status_cache: std::collections::HashMap::new(),
|
||||||
last_discovery_time: None,
|
last_discovery_time: None,
|
||||||
@ -93,6 +96,7 @@ impl SystemdCollector {
|
|||||||
|
|
||||||
// Collect service data for each monitored service
|
// Collect service data for each monitored service
|
||||||
let mut services = Vec::new();
|
let mut services = Vec::new();
|
||||||
|
let mut complete_service_data = Vec::new();
|
||||||
for service_name in &monitored_services {
|
for service_name in &monitored_services {
|
||||||
match self.get_service_status(service_name) {
|
match self.get_service_status(service_name) {
|
||||||
Ok((active_status, _detailed_info)) => {
|
Ok((active_status, _detailed_info)) => {
|
||||||
@ -149,15 +153,19 @@ impl SystemdCollector {
|
|||||||
};
|
};
|
||||||
services.push(service_info);
|
services.push(service_info);
|
||||||
|
|
||||||
// Add to AgentData with hierarchical structure
|
// Create complete service data
|
||||||
agent_data.services.push(ServiceData {
|
let service_data = ServiceData {
|
||||||
name: service_name.clone(),
|
name: service_name.clone(),
|
||||||
memory_mb,
|
memory_mb,
|
||||||
disk_gb,
|
disk_gb,
|
||||||
user_stopped: false, // TODO: Integrate with service tracker
|
user_stopped: false, // TODO: Integrate with service tracker
|
||||||
service_status: self.calculate_service_status(service_name, &active_status),
|
service_status: self.calculate_service_status(service_name, &active_status),
|
||||||
sub_services,
|
sub_services,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// Add to AgentData and cache
|
||||||
|
agent_data.services.push(service_data.clone());
|
||||||
|
complete_service_data.push(service_data);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
debug!("Failed to get status for service {}: {}", service_name, e);
|
debug!("Failed to get status for service {}: {}", service_name, e);
|
||||||
@ -170,6 +178,7 @@ impl SystemdCollector {
|
|||||||
let mut state = self.state.write().unwrap();
|
let mut state = self.state.write().unwrap();
|
||||||
state.last_collection = Some(start_time);
|
state.last_collection = Some(start_time);
|
||||||
state.services = services;
|
state.services = services;
|
||||||
|
state.cached_service_data = complete_service_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
let elapsed = start_time.elapsed();
|
let elapsed = start_time.elapsed();
|
||||||
@ -232,10 +241,6 @@ impl SystemdCollector {
|
|||||||
if needs_refresh {
|
if needs_refresh {
|
||||||
// Only check nginx sites if nginx service is active
|
// Only check nginx sites if nginx service is active
|
||||||
if state.monitored_services.iter().any(|s| s.contains("nginx")) {
|
if state.monitored_services.iter().any(|s| s.contains("nginx")) {
|
||||||
debug!(
|
|
||||||
"Refreshing nginx site latency metrics (interval: {}s)",
|
|
||||||
state.nginx_check_interval_seconds
|
|
||||||
);
|
|
||||||
let fresh_metrics = self.get_nginx_sites_internal();
|
let fresh_metrics = self.get_nginx_sites_internal();
|
||||||
state.nginx_site_metrics = fresh_metrics;
|
state.nginx_site_metrics = fresh_metrics;
|
||||||
state.last_nginx_check_time = Some(Instant::now());
|
state.last_nginx_check_time = Some(Instant::now());
|
||||||
@ -564,6 +569,16 @@ impl SystemdCollector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get cached complete service data with sub-services if available and fresh
|
||||||
|
fn get_cached_complete_services(&self) -> Option<Vec<ServiceData>> {
|
||||||
|
if !self.should_update_cache() {
|
||||||
|
let state = self.state.read().unwrap();
|
||||||
|
Some(state.cached_service_data.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get nginx sites with latency checks (internal - no caching)
|
/// Get nginx sites with latency checks (internal - no caching)
|
||||||
fn get_nginx_sites_internal(&self) -> Vec<(String, f32)> {
|
fn get_nginx_sites_internal(&self) -> Vec<(String, f32)> {
|
||||||
let mut sites = Vec::new();
|
let mut sites = Vec::new();
|
||||||
@ -571,13 +586,14 @@ impl SystemdCollector {
|
|||||||
// Discover nginx sites from configuration
|
// Discover nginx sites from configuration
|
||||||
let discovered_sites = self.discover_nginx_sites();
|
let discovered_sites = self.discover_nginx_sites();
|
||||||
|
|
||||||
|
// Always add all discovered sites, even if checks fail (like old version)
|
||||||
for (site_name, url) in &discovered_sites {
|
for (site_name, url) in &discovered_sites {
|
||||||
match self.check_site_latency(url) {
|
match self.check_site_latency(url) {
|
||||||
Ok(latency_ms) => {
|
Ok(latency_ms) => {
|
||||||
sites.push((site_name.clone(), latency_ms));
|
sites.push((site_name.clone(), latency_ms));
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// Site is unreachable - use -1.0 to indicate error
|
// Site is unreachable - use -1.0 to indicate error (like old version)
|
||||||
sites.push((site_name.clone(), -1.0));
|
sites.push((site_name.clone(), -1.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -835,18 +851,10 @@ impl SystemdCollector {
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Collector for SystemdCollector {
|
impl Collector for SystemdCollector {
|
||||||
async fn collect_structured(&self, agent_data: &mut AgentData) -> Result<(), CollectorError> {
|
async fn collect_structured(&self, agent_data: &mut AgentData) -> Result<(), CollectorError> {
|
||||||
// Use cached data if available and fresh
|
// Use cached complete data if available and fresh
|
||||||
if let Some(cached_services) = self.get_cached_services() {
|
if let Some(cached_complete_services) = self.get_cached_complete_services() {
|
||||||
debug!("Using cached systemd services data");
|
for service_data in cached_complete_services {
|
||||||
for service in cached_services {
|
agent_data.services.push(service_data);
|
||||||
agent_data.services.push(ServiceData {
|
|
||||||
name: service.name.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),
|
|
||||||
sub_services: Vec::new(), // Cached services don't have sub-services
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cm-dashboard"
|
name = "cm-dashboard"
|
||||||
version = "0.1.147"
|
version = "0.1.148"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cm-dashboard-shared"
|
name = "cm-dashboard-shared"
|
||||||
version = "0.1.147"
|
version = "0.1.148"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user