make instrumentation sync instead of async to avoid concurrency issues
This commit is contained in:
@@ -7,19 +7,11 @@ use harmony::{
|
||||
};
|
||||
use log::{error, info, log_enabled};
|
||||
use std::io::Write;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub fn init() -> tokio::task::JoinHandle<()> {
|
||||
pub fn init() {
|
||||
configure_logger();
|
||||
let handle = tokio::spawn(handle_events());
|
||||
|
||||
loop {
|
||||
if instrumentation::instrument(HarmonyEvent::HarmonyStarted).is_ok() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handle
|
||||
handle_events();
|
||||
}
|
||||
|
||||
fn configure_logger() {
|
||||
@@ -86,119 +78,114 @@ fn configure_logger() {
|
||||
.init();
|
||||
}
|
||||
|
||||
async fn handle_events() {
|
||||
let preparing_topology = Arc::new(Mutex::new(false));
|
||||
let current_score: Arc<Mutex<Option<String>>> = Arc::new(Mutex::new(None));
|
||||
fn handle_events() {
|
||||
let preparing_topology = Mutex::new(false);
|
||||
let current_score: Mutex<Option<String>> = Mutex::new(None);
|
||||
|
||||
instrumentation::subscribe("Harmony CLI Logger", {
|
||||
move |event| {
|
||||
let preparing_topology = Arc::clone(&preparing_topology);
|
||||
let current_score = Arc::clone(¤t_score);
|
||||
let mut preparing_topology = preparing_topology.lock().unwrap();
|
||||
let mut current_score = current_score.lock().unwrap();
|
||||
|
||||
async move {
|
||||
let mut preparing_topology = preparing_topology.lock().unwrap();
|
||||
let mut current_score = current_score.lock().unwrap();
|
||||
|
||||
match event {
|
||||
HarmonyEvent::HarmonyStarted => {}
|
||||
HarmonyEvent::HarmonyFinished => {
|
||||
let emoji = crate::theme::EMOJI_HARMONY.to_string();
|
||||
info!(emoji = emoji.as_str(); "Harmony completed");
|
||||
return false;
|
||||
}
|
||||
HarmonyEvent::TopologyStateChanged {
|
||||
topology,
|
||||
status,
|
||||
message,
|
||||
} => match status {
|
||||
TopologyStatus::Queued => {}
|
||||
TopologyStatus::Preparing => {
|
||||
let emoji = format!("{}", style(crate::theme::EMOJI_TOPOLOGY.to_string()).yellow());
|
||||
info!(emoji = emoji.as_str(); "Preparing environment: {topology}...");
|
||||
(*preparing_topology) = true;
|
||||
}
|
||||
TopologyStatus::Success => {
|
||||
(*preparing_topology) = false;
|
||||
if let Some(message) = message {
|
||||
info!(status = "finished"; "{message}");
|
||||
}
|
||||
}
|
||||
TopologyStatus::Noop => {
|
||||
(*preparing_topology) = false;
|
||||
if let Some(message) = message {
|
||||
info!(status = "skipped"; "{message}");
|
||||
}
|
||||
}
|
||||
TopologyStatus::Error => {
|
||||
(*preparing_topology) = false;
|
||||
if let Some(message) = message {
|
||||
error!(status = "failed"; "{message}");
|
||||
}
|
||||
}
|
||||
},
|
||||
HarmonyEvent::InterpretExecutionStarted {
|
||||
execution_id: _,
|
||||
topology: _,
|
||||
interpret: _,
|
||||
score,
|
||||
message,
|
||||
} => {
|
||||
if *preparing_topology || current_score.is_some() {
|
||||
info!("{message}");
|
||||
} else {
|
||||
(*current_score) = Some(score.clone());
|
||||
let emoji = format!("{}", style(crate::theme::EMOJI_SCORE).blue());
|
||||
info!(emoji = emoji.as_str(); "Interpreting score: {score}...");
|
||||
}
|
||||
}
|
||||
HarmonyEvent::InterpretExecutionFinished {
|
||||
execution_id: _,
|
||||
topology: _,
|
||||
interpret: _,
|
||||
score,
|
||||
outcome,
|
||||
} => {
|
||||
if current_score.is_some() && current_score.clone().unwrap() == score {
|
||||
(*current_score) = None;
|
||||
}
|
||||
|
||||
match outcome {
|
||||
Ok(outcome) => match outcome.status {
|
||||
harmony::interpret::InterpretStatus::SUCCESS => {
|
||||
info!(status = "finished"; "{}", outcome.message);
|
||||
}
|
||||
harmony::interpret::InterpretStatus::NOOP => {
|
||||
info!(status = "skipped"; "{}", outcome.message);
|
||||
}
|
||||
_ => {
|
||||
error!(status = "failed"; "{}", outcome.message);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
error!(status = "failed"; "{}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
HarmonyEvent::ApplicationFeatureStateChanged {
|
||||
topology: _,
|
||||
application,
|
||||
feature,
|
||||
status,
|
||||
} => match status {
|
||||
ApplicationFeatureStatus::Installing => {
|
||||
info!("Installing feature '{}' for '{}'...", feature, application);
|
||||
}
|
||||
ApplicationFeatureStatus::Installed => {
|
||||
info!(status = "finished"; "Feature '{}' installed", feature);
|
||||
}
|
||||
ApplicationFeatureStatus::Failed { details } => {
|
||||
error!(status = "failed"; "Feature '{}' installation failed: {}", feature, details);
|
||||
}
|
||||
},
|
||||
match event {
|
||||
HarmonyEvent::HarmonyStarted => {}
|
||||
HarmonyEvent::HarmonyFinished => {
|
||||
let emoji = crate::theme::EMOJI_HARMONY.to_string();
|
||||
info!(emoji = emoji.as_str(); "Harmony completed");
|
||||
}
|
||||
true
|
||||
HarmonyEvent::TopologyStateChanged {
|
||||
topology,
|
||||
status,
|
||||
message,
|
||||
} => match status {
|
||||
TopologyStatus::Queued => {}
|
||||
TopologyStatus::Preparing => {
|
||||
let emoji = format!(
|
||||
"{}",
|
||||
style(crate::theme::EMOJI_TOPOLOGY.to_string()).yellow()
|
||||
);
|
||||
info!(emoji = emoji.as_str(); "Preparing environment: {topology}...");
|
||||
(*preparing_topology) = true;
|
||||
}
|
||||
TopologyStatus::Success => {
|
||||
(*preparing_topology) = false;
|
||||
if let Some(message) = message {
|
||||
info!(status = "finished"; "{message}");
|
||||
}
|
||||
}
|
||||
TopologyStatus::Noop => {
|
||||
(*preparing_topology) = false;
|
||||
if let Some(message) = message {
|
||||
info!(status = "skipped"; "{message}");
|
||||
}
|
||||
}
|
||||
TopologyStatus::Error => {
|
||||
(*preparing_topology) = false;
|
||||
if let Some(message) = message {
|
||||
error!(status = "failed"; "{message}");
|
||||
}
|
||||
}
|
||||
},
|
||||
HarmonyEvent::InterpretExecutionStarted {
|
||||
execution_id: _,
|
||||
topology: _,
|
||||
interpret: _,
|
||||
score,
|
||||
message,
|
||||
} => {
|
||||
if *preparing_topology || current_score.is_some() {
|
||||
info!("{message}");
|
||||
} else {
|
||||
(*current_score) = Some(score.clone());
|
||||
let emoji = format!("{}", style(crate::theme::EMOJI_SCORE).blue());
|
||||
info!(emoji = emoji.as_str(); "Interpreting score: {score}...");
|
||||
}
|
||||
}
|
||||
HarmonyEvent::InterpretExecutionFinished {
|
||||
execution_id: _,
|
||||
topology: _,
|
||||
interpret: _,
|
||||
score,
|
||||
outcome,
|
||||
} => {
|
||||
if current_score.is_some() && ¤t_score.clone().unwrap() == score {
|
||||
(*current_score) = None;
|
||||
}
|
||||
|
||||
match outcome {
|
||||
Ok(outcome) => match outcome.status {
|
||||
harmony::interpret::InterpretStatus::SUCCESS => {
|
||||
info!(status = "finished"; "{}", outcome.message);
|
||||
}
|
||||
harmony::interpret::InterpretStatus::NOOP => {
|
||||
info!(status = "skipped"; "{}", outcome.message);
|
||||
}
|
||||
_ => {
|
||||
error!(status = "failed"; "{}", outcome.message);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
error!(status = "failed"; "{err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
HarmonyEvent::ApplicationFeatureStateChanged {
|
||||
topology: _,
|
||||
application,
|
||||
feature,
|
||||
status,
|
||||
} => match status {
|
||||
ApplicationFeatureStatus::Installing => {
|
||||
info!("Installing feature '{feature}' for '{application}'...");
|
||||
}
|
||||
ApplicationFeatureStatus::Installed => {
|
||||
info!(status = "finished"; "Feature '{feature}' installed");
|
||||
}
|
||||
ApplicationFeatureStatus::Failed { details } => {
|
||||
error!(status = "failed"; "Feature '{feature}' installation failed: {details}");
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
.await;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ pub async fn run_cli<T: Topology + Send + Sync + 'static>(
|
||||
scores: Vec<Box<dyn Score<T>>>,
|
||||
args: Args,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let cli_logger_handle = cli_logger::init();
|
||||
cli_logger::init();
|
||||
|
||||
let mut maestro = Maestro::initialize(inventory, topology).await.unwrap();
|
||||
maestro.register_all(scores);
|
||||
@@ -123,7 +123,6 @@ pub async fn run_cli<T: Topology + Send + Sync + 'static>(
|
||||
let result = init(maestro, args).await;
|
||||
|
||||
instrumentation::instrument(instrumentation::HarmonyEvent::HarmonyFinished).unwrap();
|
||||
let _ = tokio::try_join!(cli_logger_handle);
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user