use indicatif::{MultiProgress, ProgressBar}; use indicatif_log_bridge::LogWrapper; use log::error; use std::{ collections::HashMap, sync::{Arc, Mutex}, }; use crate::instrumentation::{self, HarmonyComposerEvent}; pub fn init() -> tokio::task::JoinHandle<()> { configure_logger(); let handle = tokio::spawn(handle_events()); loop { if instrumentation::instrument(HarmonyComposerEvent::HarmonyComposerStarted).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); } pub async fn handle_events() { const PROGRESS_SETUP: &str = "project-initialization"; const PROGRESS_DEPLOYMENT: &str = "deployment"; instrumentation::subscribe("Harmony Composer Logger", { let progresses: Arc>> = Arc::new(Mutex::new(HashMap::new())); let compilation_progress = Arc::new(Mutex::new(None::)); move |event| { let progresses_clone = Arc::clone(&progresses); let compilation_progress_clone = Arc::clone(&compilation_progress); async move { let mut progresses_guard = progresses_clone.lock().unwrap(); let mut compilation_progress_guard = compilation_progress_clone.lock().unwrap(); match event { HarmonyComposerEvent::HarmonyComposerStarted => {} HarmonyComposerEvent::ProjectInitializationStarted => { let multi_progress = harmony_cli::progress::new_section(format!( "{} Initializing Harmony project...", harmony_cli::theme::EMOJI_HARMONY, )); (*progresses_guard).insert(PROGRESS_SETUP.to_string(), multi_progress); } HarmonyComposerEvent::ProjectInitialized => println!("\n"), HarmonyComposerEvent::ProjectCompilationStarted { details } => { let initialization_progress = (*progresses_guard).get(PROGRESS_SETUP).unwrap(); let _ = initialization_progress.clear(); let progress = harmony_cli::progress::add_spinner(initialization_progress, details); *compilation_progress_guard = Some(progress); } HarmonyComposerEvent::ProjectCompiled => { let initialization_progress = (*progresses_guard).get(PROGRESS_SETUP).unwrap(); harmony_cli::progress::success( initialization_progress, (*compilation_progress_guard).take(), "project compiled".to_string(), ); } HarmonyComposerEvent::ProjectCompilationFailed { details } => { let initialization_progress = (*progresses_guard).get(PROGRESS_SETUP).unwrap(); harmony_cli::progress::error( initialization_progress, (*compilation_progress_guard).take(), "failed to compile project".to_string(), ); error!("{details}"); } HarmonyComposerEvent::DeploymentStarted { target } => { let multi_progress = harmony_cli::progress::new_section(format!( "{} Starting deployment to {target}...\n\n", harmony_cli::theme::EMOJI_DEPLOY )); (*progresses_guard).insert(PROGRESS_DEPLOYMENT.to_string(), multi_progress); } HarmonyComposerEvent::DeploymentCompleted { details } => println!("\n"), HarmonyComposerEvent::Shutdown => { for (_, progresses) in (*progresses_guard).iter() { progresses.clear().unwrap(); } return false; } } true } } }) .await }