use anyhow::Result; use clap::Parser; use std::process; use tracing::{error, info}; use tracing_subscriber::EnvFilter; mod app; mod communication; mod config; mod metrics; mod ui; use app::Dashboard; /// Check if running inside tmux session fn check_tmux_session() { // Check for TMUX environment variable which is set when inside a tmux session if std::env::var("TMUX").is_err() { eprintln!("╭─────────────────────────────────────────────────────────────╮"); eprintln!("│ ⚠️ TMUX REQUIRED │"); eprintln!("├─────────────────────────────────────────────────────────────┤"); eprintln!("│ CM Dashboard must be run inside a tmux session for proper │"); eprintln!("│ terminal handling and remote operation functionality. │"); eprintln!("│ │"); eprintln!("│ Please start a tmux session first: │"); eprintln!("│ tmux new-session -d -s dashboard cm-dashboard │"); eprintln!("│ tmux attach-session -t dashboard │"); eprintln!("│ │"); eprintln!("│ Or simply: │"); eprintln!("│ tmux │"); eprintln!("│ cm-dashboard │"); eprintln!("╰─────────────────────────────────────────────────────────────╯"); process::exit(1); } } #[derive(Parser)] #[command(name = "cm-dashboard")] #[command(about = "CM Dashboard TUI with individual metric consumption")] #[command(version)] struct Cli { /// Increase logging verbosity (-v, -vv) #[arg(short, long, action = clap::ArgAction::Count)] verbose: u8, /// Configuration file path (defaults to /etc/cm-dashboard/dashboard.toml) #[arg(short, long)] config: Option, /// Run in headless mode (no TUI, just logging) #[arg(long)] headless: bool, } #[tokio::main] async fn main() -> Result<()> { let cli = Cli::parse(); // Setup logging - only if headless or verbose if cli.headless || cli.verbose > 0 { let log_level = match cli.verbose { 0 => "warn", // Only warnings and errors when not verbose 1 => "info", 2 => "debug", _ => "trace", }; tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env().add_directive(log_level.parse()?)) .init(); } else { // No logging output when running TUI mode tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env().add_directive("off".parse()?)) .init(); } // Check for tmux session requirement (only for TUI mode) if !cli.headless { check_tmux_session(); } if cli.headless || cli.verbose > 0 { info!("CM Dashboard starting with individual metrics architecture..."); } // Create and run dashboard let mut dashboard = Dashboard::new(cli.config, cli.headless).await?; // Setup graceful shutdown let ctrl_c = async { tokio::signal::ctrl_c() .await .expect("failed to install Ctrl+C handler"); }; // Run dashboard with graceful shutdown tokio::select! { result = dashboard.run() => { if let Err(e) = result { error!("Dashboard error: {}", e); return Err(e); } } _ = ctrl_c => { info!("Shutdown signal received"); } } if cli.headless || cli.verbose > 0 { info!("Dashboard shutdown complete"); } Ok(()) }