use harmony::instrumentation::{self, HarmonyEvent}; use indicatif::{MultiProgress, ProgressBar}; use indicatif_log_bridge::LogWrapper; use std::{ collections::{HashMap, hash_map}, sync::{Arc, Mutex}, }; use crate::progress; pub fn init() -> tokio::task::JoinHandle<()> { configure_logger(); let handle = tokio::spawn(handle_events()); loop { if instrumentation::instrument(HarmonyEvent::HarmonyStarted).is_ok() { break; } } handle } fn configure_logger() { let logger = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).build(); let level = logger.filter(); let multi = MultiProgress::new(); LogWrapper::new(multi.clone(), logger).try_init().unwrap(); log::set_max_level(level); } async fn handle_events() { instrumentation::subscribe("Harmony CLI Logger", { let sections: Arc>> = Arc::new(Mutex::new(HashMap::new())); let progress_bars: Arc>> = Arc::new(Mutex::new(HashMap::new())); move |event| { let sections_clone = Arc::clone(§ions); let progress_bars_clone = Arc::clone(&progress_bars); async move { let mut sections = sections_clone.lock().unwrap(); let mut progress_bars = progress_bars_clone.lock().unwrap(); match event { HarmonyEvent::HarmonyStarted => {} HarmonyEvent::PrepareTopologyStarted { topology: name } => { let section = progress::new_section(format!( "{} Preparing environment: {name}...", crate::theme::EMOJI_TOPOLOGY, )); (*sections).insert(name, section); } HarmonyEvent::TopologyPrepared { topology: name, outcome, } => { let section = (*sections).get(&name).unwrap(); let progress = progress::add_spinner(section, "".into()); match outcome.status { harmony::interpret::InterpretStatus::SUCCESS => { progress::success(section, Some(progress), outcome.message); } harmony::interpret::InterpretStatus::FAILURE => { progress::error(section, Some(progress), outcome.message); } harmony::interpret::InterpretStatus::RUNNING => todo!(), harmony::interpret::InterpretStatus::QUEUED => todo!(), harmony::interpret::InterpretStatus::BLOCKED => todo!(), harmony::interpret::InterpretStatus::NOOP => { progress::skip(section, Some(progress), outcome.message); } } } HarmonyEvent::InterpretExecutionStarted { interpret: name, topology, message, } => { let section = (*sections).get(&topology).unwrap(); let progress_bar = progress::add_spinner(section, message); (*progress_bars).insert(name, progress_bar); } HarmonyEvent::InterpretExecutionFinished { topology, interpret: name, outcome, } => { let section = (*sections).get(&topology).unwrap(); let progress_bar = (*progress_bars).get(&name).cloned(); let _ = section.clear(); match outcome { Ok(outcome) => { progress::success(section, progress_bar, outcome.message); } Err(err) => { progress::error(section, progress_bar, err.to_string()); } } (*progress_bars).remove(&name); } } true } } }) .await; }