xbp 10.17.2

XBP is a zero-config build pack that can also interact with proxies, kafka, sockets, synthetic monitors.
Documentation
use crate::cli::commands;
use crate::cli::error::{CliResult, ErrorFactory};
use xbp_monitoring::{list_items, run_all_once, serve, RunKind};

pub async fn handle_monitoring(cmd: commands::MonitoringCmd) -> CliResult<()> {
    match cmd.command {
        commands::MonitoringSubCommand::Serve { file } => {
            if let Err(err) = serve(&file).await {
                return Err(ErrorFactory::operation(
                    "monitoring",
                    "start monitoring service",
                    err.to_string(),
                    Some("Validate your monitoring config file and paths."),
                ));
            }
        }
        commands::MonitoringSubCommand::RunOnce {
            file,
            probes_only,
            stories_only,
        } => {
            let results = run_all_once(&file, probes_only, stories_only)
                .await
                .map_err(|e| {
                    ErrorFactory::operation(
                        "monitoring",
                        "run monitoring checks once",
                        e.to_string(),
                        Some("Check YAML syntax and monitor target URLs."),
                    )
                })?;
            if results.is_empty() {
                println!("No probes or stories configured");
            } else {
                for result in results {
                    let label = match result.kind {
                        RunKind::Probe => "probe",
                        RunKind::Story => "story",
                    };
                    if result.success {
                        println!("{} {}", label, result.name);
                    } else {
                        let code = result
                            .status_code
                            .map(|c| c.to_string())
                            .unwrap_or_else(|| "-".into());
                        let err = result.error.unwrap_or_else(|| "Unknown error".into());
                        println!("{} {} ✗ (code {}, {})", label, result.name, code, err);
                    }
                }
            }
        }
        commands::MonitoringSubCommand::List { file } => {
            let (probes, stories) = list_items(&file).await.map_err(|e| {
                ErrorFactory::operation(
                    "monitoring",
                    "list monitoring items",
                    e.to_string(),
                    Some("Ensure the config file exists and is readable."),
                )
            })?;
            println!(
                "Probes: {}",
                if probes.is_empty() {
                    "none".into()
                } else {
                    probes.join(", ")
                }
            );
            println!(
                "Stories: {}",
                if stories.is_empty() {
                    "none".into()
                } else {
                    stories.join(", ")
                }
            );
        }
    }
    Ok(())
}