All checks were successful
Build and Release / build-and-release (push) Successful in 2m34s
Add comprehensive tracking for services stopped via dashboard to prevent false alerts when users intentionally stop services. Features: - User-stopped services report Status::Ok instead of Warning - Persistent storage survives agent restarts - Dashboard sends UserStart/UserStop commands - Agent tracks and syncs user-stopped state globally - Systemd collector respects user-stopped flags Implementation: - New service_tracker module with persistent JSON storage - Enhanced ServiceAction enum with UserStart/UserStop variants - Global singleton tracker accessible by collectors - Service status logic updated to check user-stopped flag - Dashboard version now uses CARGO_PKG_VERSION automatically Bump version to v0.1.43
95 lines
2.7 KiB
Rust
95 lines
2.7 KiB
Rust
use anyhow::Result;
|
|
use clap::Parser;
|
|
use tracing::{error, info};
|
|
use tracing_subscriber::EnvFilter;
|
|
|
|
mod agent;
|
|
mod collectors;
|
|
mod communication;
|
|
mod config;
|
|
mod metrics;
|
|
mod notifications;
|
|
mod service_tracker;
|
|
mod status;
|
|
|
|
use agent::Agent;
|
|
|
|
/// Get version showing cm-dashboard-agent package hash for easy deployment verification
|
|
fn get_version() -> &'static str {
|
|
// Get the path of the current executable
|
|
let exe_path = std::env::current_exe().expect("Failed to get executable path");
|
|
let exe_str = exe_path.to_string_lossy();
|
|
|
|
// Extract Nix store hash from path like /nix/store/HASH-cm-dashboard-v0.1.8/bin/cm-dashboard-agent
|
|
let hash_part = exe_str.strip_prefix("/nix/store/").expect("Not a nix store path");
|
|
let hash = hash_part.split('-').next().expect("Invalid nix store path format");
|
|
assert!(hash.len() >= 8, "Hash too short");
|
|
|
|
// Return first 8 characters of nix store hash
|
|
let short_hash = hash[..8].to_string();
|
|
Box::leak(short_hash.into_boxed_str())
|
|
}
|
|
|
|
#[derive(Parser)]
|
|
#[command(name = "cm-dashboard-agent")]
|
|
#[command(about = "CM Dashboard metrics agent with individual metric collection")]
|
|
#[command(version = get_version())]
|
|
struct Cli {
|
|
/// Increase logging verbosity (-v, -vv)
|
|
#[arg(short, long, action = clap::ArgAction::Count)]
|
|
verbose: u8,
|
|
|
|
/// Configuration file path (required)
|
|
#[arg(short, long)]
|
|
config: String,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
let cli = Cli::parse();
|
|
|
|
// Setup logging
|
|
let log_level = match cli.verbose {
|
|
0 => "info",
|
|
1 => "debug",
|
|
_ => "trace",
|
|
};
|
|
|
|
tracing_subscriber::fmt()
|
|
.with_env_filter(EnvFilter::from_default_env().add_directive(log_level.parse()?))
|
|
.init();
|
|
|
|
info!("CM Dashboard Agent starting with individual metrics architecture...");
|
|
|
|
// Create and run agent
|
|
let mut agent = Agent::new(Some(cli.config)).await?;
|
|
|
|
// Setup graceful shutdown channel
|
|
let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel();
|
|
|
|
let ctrl_c = async {
|
|
tokio::signal::ctrl_c()
|
|
.await
|
|
.expect("failed to install Ctrl+C handler");
|
|
};
|
|
|
|
// Run agent with graceful shutdown
|
|
tokio::select! {
|
|
result = agent.run(shutdown_rx) => {
|
|
if let Err(e) = result {
|
|
error!("Agent error: {}", e);
|
|
return Err(e);
|
|
}
|
|
}
|
|
_ = ctrl_c => {
|
|
info!("Shutdown signal received, stopping agent...");
|
|
let _ = shutdown_tx.send(());
|
|
// Give agent time to shutdown gracefully
|
|
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
|
}
|
|
}
|
|
|
|
info!("Agent shutdown complete");
|
|
Ok(())
|
|
}
|