use std::time::Duration; use tracing::Level; mod health; mod messaging; #[tokio::main] async fn main() -> anyhow::Result<()> { let subscriber = tracing_subscriber::fmt() .with_max_level(Level::TRACE) .finish(); tracing::subscriber::set_global_default(subscriber) .expect("to set a tracing global subscriber"); run().await.map_err(|err| { tracing::error!(cause = %err, "could not start agent"); err }) } async fn run() -> anyhow::Result<()> { let agent = messaging::Agent::connect("demo_agent").await?; tracing::info!("initialized messaging system"); init_health_subsystem(agent.clone()); tracing::info!("initialized health system"); tracing::info!("agent is ready"); tokio::signal::ctrl_c().await?; Ok(()) } fn init_health_subsystem(agent: messaging::Agent) { let mut system = health::System::new(); let health_monitor = health::HealthMonitor::new(); let health_monitor_clone = health_monitor.clone(); // Forever refresh system resources and monitor changes std::thread::spawn(move || loop { const REFRESH_INTERVAL: Duration = Duration::from_secs(1); system.refresh_resources(); health_monitor.check_system(&system); std::thread::sleep(REFRESH_INTERVAL); }); tokio::spawn(async move { let mut recv = health_monitor_clone.monitor(); while let Ok(()) = recv.changed().await { tracing::info!(health = ?&*recv.borrow(), "health watermark"); let payload = serde_json::to_string(&*recv.borrow()).expect("serializable health"); let message = messaging::OutgoingMessage::Health(payload); agent.publish(message).await; } }); }