All checks were successful
Build and Release / build-and-release (push) Successful in 1m11s
- Fix /tmp usage status to use proper thresholds instead of hardcoded Ok status - Fix wear level status to use configurable thresholds instead of hardcoded values - Add dedicated tmp_status field to SystemWidget for proper /tmp status display - Remove host-level hourglass icon during service operations - Implement immediate service status updates after start/stop/restart commands - Remove active users display and collection from NixOS section - Fix immediate host status aggregation transmission to dashboard
156 lines
5.5 KiB
Rust
156 lines
5.5 KiB
Rust
use async_trait::async_trait;
|
|
use cm_dashboard_shared::{Metric, MetricValue, Status, StatusTracker};
|
|
use std::process::Command;
|
|
use tracing::debug;
|
|
|
|
use super::{Collector, CollectorError};
|
|
use crate::config::NixOSConfig;
|
|
|
|
/// NixOS system information collector
|
|
///
|
|
/// Collects NixOS-specific system information including:
|
|
/// - NixOS version and build information
|
|
pub struct NixOSCollector {
|
|
}
|
|
|
|
impl NixOSCollector {
|
|
pub fn new(_config: NixOSConfig) -> Self {
|
|
Self {}
|
|
}
|
|
|
|
|
|
/// Get agent hash from binary path
|
|
fn get_agent_hash(&self) -> Result<String, Box<dyn std::error::Error>> {
|
|
// Get the path of the current executable
|
|
let exe_path = std::env::current_exe()?;
|
|
let exe_str = exe_path.to_string_lossy();
|
|
|
|
// Extract Nix store hash from path like /nix/store/fn804fh332mp8gz06qawminpj20xl25h-cm-dashboard-0.1.0/bin/cm-dashboard-agent
|
|
if let Some(store_path) = exe_str.strip_prefix("/nix/store/") {
|
|
if let Some(dash_pos) = store_path.find('-') {
|
|
return Ok(store_path[..dash_pos].to_string());
|
|
}
|
|
}
|
|
|
|
// Fallback to "unknown" if not in Nix store
|
|
Ok("unknown".to_string())
|
|
}
|
|
|
|
/// Get configuration hash from deployed nix store system
|
|
fn get_config_hash(&self) -> Result<String, Box<dyn std::error::Error>> {
|
|
// Read the symlink target of /run/current-system to get nix store path
|
|
let output = Command::new("readlink")
|
|
.arg("/run/current-system")
|
|
.output()?;
|
|
|
|
if !output.status.success() {
|
|
return Err("readlink command failed".into());
|
|
}
|
|
|
|
let binding = String::from_utf8_lossy(&output.stdout);
|
|
let store_path = binding.trim();
|
|
|
|
// Extract hash from nix store path
|
|
// Format: /nix/store/HASH-nixos-system-HOSTNAME-VERSION
|
|
if let Some(hash_part) = store_path.strip_prefix("/nix/store/") {
|
|
if let Some(hash) = hash_part.split('-').next() {
|
|
if hash.len() >= 8 {
|
|
// Return first 8 characters of nix store hash
|
|
return Ok(hash[..8].to_string());
|
|
}
|
|
}
|
|
}
|
|
|
|
Err("Could not extract hash from nix store path".into())
|
|
}
|
|
|
|
}
|
|
|
|
#[async_trait]
|
|
impl Collector for NixOSCollector {
|
|
|
|
async fn collect(&self, _status_tracker: &mut StatusTracker) -> Result<Vec<Metric>, CollectorError> {
|
|
debug!("Collecting NixOS system information");
|
|
let mut metrics = Vec::new();
|
|
let timestamp = chrono::Utc::now().timestamp() as u64;
|
|
|
|
// Collect NixOS build information (config hash)
|
|
match self.get_config_hash() {
|
|
Ok(config_hash) => {
|
|
metrics.push(Metric {
|
|
name: "system_nixos_build".to_string(),
|
|
value: MetricValue::String(config_hash),
|
|
unit: None,
|
|
description: Some("NixOS deployed configuration hash".to_string()),
|
|
status: Status::Ok,
|
|
timestamp,
|
|
});
|
|
}
|
|
Err(e) => {
|
|
debug!("Failed to get config hash: {}", e);
|
|
metrics.push(Metric {
|
|
name: "system_nixos_build".to_string(),
|
|
value: MetricValue::String("unknown".to_string()),
|
|
unit: None,
|
|
description: Some("NixOS config hash (failed to detect)".to_string()),
|
|
status: Status::Unknown,
|
|
timestamp,
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
// Collect config hash
|
|
match self.get_config_hash() {
|
|
Ok(hash) => {
|
|
metrics.push(Metric {
|
|
name: "system_config_hash".to_string(),
|
|
value: MetricValue::String(hash),
|
|
unit: None,
|
|
description: Some("NixOS deployed configuration hash".to_string()),
|
|
status: Status::Ok,
|
|
timestamp,
|
|
});
|
|
}
|
|
Err(e) => {
|
|
debug!("Failed to get config hash: {}", e);
|
|
metrics.push(Metric {
|
|
name: "system_config_hash".to_string(),
|
|
value: MetricValue::String("unknown".to_string()),
|
|
unit: None,
|
|
description: Some("Deployed config hash (failed to detect)".to_string()),
|
|
status: Status::Unknown,
|
|
timestamp,
|
|
});
|
|
}
|
|
}
|
|
|
|
// Collect agent hash
|
|
match self.get_agent_hash() {
|
|
Ok(hash) => {
|
|
metrics.push(Metric {
|
|
name: "system_agent_hash".to_string(),
|
|
value: MetricValue::String(hash),
|
|
unit: None,
|
|
description: Some("Agent Nix store hash".to_string()),
|
|
status: Status::Ok,
|
|
timestamp,
|
|
});
|
|
}
|
|
Err(e) => {
|
|
debug!("Failed to get agent hash: {}", e);
|
|
metrics.push(Metric {
|
|
name: "system_agent_hash".to_string(),
|
|
value: MetricValue::String("unknown".to_string()),
|
|
unit: None,
|
|
description: Some("Agent hash (failed to detect)".to_string()),
|
|
status: Status::Unknown,
|
|
timestamp,
|
|
});
|
|
}
|
|
}
|
|
|
|
debug!("Collected {} NixOS metrics", metrics.len());
|
|
Ok(metrics)
|
|
}
|
|
} |