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 status; use agent::Agent; #[derive(Parser)] #[command(name = "cm-dashboard-agent")] #[command(about = "CM Dashboard metrics agent with individual metric collection")] #[command(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(()) }