Make dashboard -V show the same hash as the agent by extracting the hash from the dashboard binary's nix store path instead of the system configuration path. Now both will show identical hashes since they're from the same cm-dashboard package.
103 lines
3.0 KiB
Rust
103 lines
3.0 KiB
Rust
use anyhow::Result;
|
|
use clap::Parser;
|
|
use tracing::{error, info};
|
|
use tracing_subscriber::EnvFilter;
|
|
|
|
mod app;
|
|
mod communication;
|
|
mod config;
|
|
mod metrics;
|
|
mod ui;
|
|
|
|
use app::Dashboard;
|
|
|
|
/// Get version showing cm-dashboard package hash for easy rebuild 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-0.1.0/bin/cm-dashboard
|
|
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")]
|
|
#[command(about = "CM Dashboard TUI with individual metric consumption")]
|
|
#[command(version = get_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<String>,
|
|
|
|
/// 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();
|
|
}
|
|
|
|
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(())
|
|
}
|