diff --git a/dsc/Cargo.toml b/dsc/Cargo.toml index ee0abb9b..e1275d38 100644 --- a/dsc/Cargo.toml +++ b/dsc/Cargo.toml @@ -17,6 +17,7 @@ clap_complete = { version = "4.4" } crossterm = { version = "0.27" } ctrlc = { version = "3.4.0" } dsc_lib = { path = "../dsc_lib" } +indicatif = { version = "0.17" } jsonschema = "0.17" path-absolutize = { version = "3.1.1" } schemars = { version = "0.8.12" } diff --git a/dsc_lib/Cargo.toml b/dsc_lib/Cargo.toml index 13f8fcef..233fd8fa 100644 --- a/dsc_lib/Cargo.toml +++ b/dsc_lib/Cargo.toml @@ -18,6 +18,7 @@ thiserror = "1.0" chrono = "0.4.26" security_context_lib = { path = "../security_context_lib" } tracing = "0.1.37" +tracing-indicatif = { version = "0.3.6" } tree-sitter = "0.20" tree-sitter-dscexpression = { path = "../tree-sitter-dscexpression" } diff --git a/dsc_lib/src/configure/mod.rs b/dsc_lib/src/configure/mod.rs index fea522b1..8c116eda 100644 --- a/dsc_lib/src/configure/mod.rs +++ b/dsc_lib/src/configure/mod.rs @@ -13,12 +13,12 @@ use self::config_doc::{Configuration, DataType, Metadata, SecurityContextKind}; use self::depends_on::get_resource_invocation_order; use self::config_result::{ConfigurationGetResult, ConfigurationSetResult, ConfigurationTestResult, ConfigurationExportResult}; use self::contraints::{check_length, check_number_limits, check_allowed_values}; -use indicatif::{ProgressBar, ProgressStyle}; +use indicatif::ProgressStyle; use security_context_lib::{SecurityContext, get_security_context}; use serde_json::{Map, Value}; -use std::collections::HashMap; -use std::time::Duration; -use tracing::{debug, trace}; +use std::{collections::HashMap, mem}; +use tracing::{debug, trace, warn_span, Span}; +use tracing_indicatif::span_ext::IndicatifSpanExt; pub mod context; pub mod config_doc; @@ -135,13 +135,14 @@ fn escape_property_values(properties: &Map) -> Result Result { - let pb = ProgressBar::new(len); - pb.enable_steady_tick(Duration::from_millis(120)); - pb.set_style(ProgressStyle::with_template( +fn get_progress_bar_span(len: u64) -> Result { + // use warn_span since that is the default logging level but progress bars will be suppressed if error trace level is used + let pb_span = warn_span!(""); + pb_span.pb_set_style(&ProgressStyle::with_template( "{spinner:.green} [{elapsed_precise:.cyan}] [{bar:40.cyan/blue}] {pos:>7}/{len:7} {msg:.yellow}" )?); - Ok(pb) + pb_span.pb_set_length(len); + Ok(pb_span) } fn add_metadata(kind: &Kind, mut properties: Option> ) -> Result { @@ -226,10 +227,11 @@ impl Configurator { let config = self.validate_config()?; let mut result = ConfigurationGetResult::new(); let resources = get_resource_invocation_order(&config, &mut self.statement_parser, &self.context)?; - let pb = get_progress_bar(resources.len() as u64)?; + let pb_span = get_progress_bar_span(resources.len() as u64)?; + let pb_span_enter = pb_span.enter(); for resource in resources { - pb.inc(1); - pb.set_message(format!("Get '{}'", resource.name)); + Span::current().pb_inc(1); + pb_span.pb_set_message(format!("Get '{}'", resource.name).as_str()); let properties = self.invoke_property_expressions(&resource.properties)?; let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type.to_lowercase()) else { return Err(DscError::ResourceNotFound(resource.resource_type)); @@ -246,7 +248,8 @@ impl Configurator { result.results.push(resource_result); } - pb.finish_with_message("Get configuration completed"); + std::mem::drop(pb_span_enter); + std::mem::drop(pb_span); Ok(result) } @@ -264,10 +267,11 @@ impl Configurator { let config = self.validate_config()?; let mut result = ConfigurationSetResult::new(); let resources = get_resource_invocation_order(&config, &mut self.statement_parser, &self.context)?; - let pb = get_progress_bar(resources.len() as u64)?; + let pb_span = get_progress_bar_span(resources.len() as u64)?; + let pb_span_enter = pb_span.enter(); for resource in resources { - pb.inc(1); - pb.set_message(format!("Set '{}'", resource.name)); + Span::current().pb_inc(1); + pb_span.pb_set_message(format!("Set '{}'", resource.name).as_str()); let properties = self.invoke_property_expressions(&resource.properties)?; let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type.to_lowercase()) else { return Err(DscError::ResourceNotFound(resource.resource_type)); @@ -284,7 +288,8 @@ impl Configurator { result.results.push(resource_result); } - pb.finish_with_message("Set configuration completed"); + mem::drop(pb_span_enter); + mem::drop(pb_span); Ok(result) } @@ -302,10 +307,11 @@ impl Configurator { let config = self.validate_config()?; let mut result = ConfigurationTestResult::new(); let resources = get_resource_invocation_order(&config, &mut self.statement_parser, &self.context)?; - let pb = get_progress_bar(resources.len() as u64)?; + let pb_span = get_progress_bar_span(resources.len() as u64)?; + let pb_span_enter = pb_span.enter(); for resource in resources { - pb.inc(1); - pb.set_message(format!("Test '{}'", resource.name)); + Span::current().pb_inc(1); + pb_span.pb_set_message(format!("Test '{}'", resource.name).as_str()); let properties = self.invoke_property_expressions(&resource.properties)?; let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type.to_lowercase()) else { return Err(DscError::ResourceNotFound(resource.resource_type)); @@ -322,7 +328,8 @@ impl Configurator { result.results.push(resource_result); } - pb.finish_with_message("Test configuration completed"); + std::mem::drop(pb_span_enter); + std::mem::drop(pb_span); Ok(result) } @@ -346,10 +353,11 @@ impl Configurator { let mut result = ConfigurationExportResult::new(); let mut conf = config_doc::Configuration::new(); - let pb = get_progress_bar(config.resources.len() as u64)?; + let pb_span = get_progress_bar_span(config.resources.len() as u64)?; + let pb_span_enter = pb_span.enter(); for resource in config.resources { - pb.inc(1); - pb.set_message(format!("Export '{}'", resource.name)); + Span::current().pb_inc(1); + pb_span.pb_set_message(format!("Export '{}'", resource.name).as_str()); let properties = self.invoke_property_expressions(&resource.properties)?; let Some(dsc_resource) = self.discovery.find_resource(&resource.resource_type.to_lowercase()) else { return Err(DscError::ResourceNotFound(resource.resource_type.clone())); @@ -359,8 +367,9 @@ impl Configurator { add_resource_export_results_to_configuration(dsc_resource, Some(dsc_resource), &mut conf, input.as_str())?; } + std::mem::drop(pb_span_enter); + std::mem::drop(pb_span); result.result = Some(conf); - pb.finish_with_message("Export configuration completed"); Ok(result) } diff --git a/dsc_lib/src/discovery/command_discovery.rs b/dsc_lib/src/discovery/command_discovery.rs index 1a59ec69..12d9c20d 100644 --- a/dsc_lib/src/discovery/command_discovery.rs +++ b/dsc_lib/src/discovery/command_discovery.rs @@ -6,15 +6,15 @@ use crate::dscresources::dscresource::{Capability, DscResource, ImplementedAs}; use crate::dscresources::resource_manifest::{import_manifest, Kind, ResourceManifest}; use crate::dscresources::command_resource::invoke_command; use crate::dscerror::DscError; -use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; +use indicatif::ProgressStyle; use std::collections::BTreeMap; use std::env; use std::ffi::OsStr; use std::fs::File; use std::io::BufReader; use std::path::Path; -use std::time::Duration; -use tracing::{debug, error, trace, warn}; +use tracing::{debug, error, trace, warn, warn_span, Span}; +use tracing_indicatif::span_ext::IndicatifSpanExt; pub struct CommandDiscovery { } @@ -31,25 +31,18 @@ impl CommandDiscovery { debug!("Searching for resources: {:?}", required_resource_types); let return_all_resources = required_resource_types.len() == 1 && required_resource_types[0] == "*"; - let multi_progress_bar = MultiProgress::new(); - let pb = multi_progress_bar.add( + let pb_span = warn_span!(""); if return_all_resources { - let pb = ProgressBar::new(1); - pb.enable_steady_tick(Duration::from_millis(120)); - pb.set_style(ProgressStyle::with_template( - "{spinner:.green} [{elapsed_precise:.cyan}] {msg:.yellow}" - )?); - pb - } else { - let pb = ProgressBar::new(required_resource_types.len() as u64); - pb.enable_steady_tick(Duration::from_millis(120)); - pb.set_style(ProgressStyle::with_template( - "{spinner:.green} [{elapsed_precise:.cyan}] [{bar:40.cyan/blue}] {pos:>7}/{len:7} {msg:.yellow}" - )?); - pb - } - ); - pb.set_message("Searching for resources"); + pb_span.pb_set_style(&ProgressStyle::with_template( + "{spinner:.green} [{elapsed_precise:.cyan}] {msg:.yellow}" + )?); + } else { + pb_span.pb_set_style(&ProgressStyle::with_template( + "{spinner:.green} [{elapsed_precise:.cyan}] [{bar:40.cyan/blue}] {pos:>7}/{len:7} {msg:.yellow}" + )?); + } + pb_span.pb_set_message("Searching for resources"); + let _ = pb_span.enter(); let mut resources: BTreeMap = BTreeMap::new(); let mut adapter_resources: Vec = Vec::new(); @@ -128,7 +121,7 @@ impl CommandDiscovery { { remaining_required_resource_types.retain(|x| *x != resource.type_name.to_lowercase()); debug!("Found {} in {}", &resource.type_name, path.display()); - pb.inc(1); + Span::current().pb_inc(1); resources.insert(resource.type_name.to_lowercase(), resource); if remaining_required_resource_types.is_empty() { @@ -140,18 +133,17 @@ impl CommandDiscovery { } } } - debug!("Found {} matching non-adapter resources", resources.len() - adapter_resources.len()); // now go through the adapter resources and add them to the list of resources for adapter in adapter_resources { debug!("Enumerating resources for adapter {}", adapter); - let pb_adapter = multi_progress_bar.add(ProgressBar::new(1)); - pb_adapter.enable_steady_tick(Duration::from_millis(120)); - pb_adapter.set_style(ProgressStyle::with_template( + let pb_adapter_span = warn_span!(""); + pb_adapter_span.pb_set_style(&ProgressStyle::with_template( "{spinner:.green} [{elapsed_precise:.cyan}] {msg:.white}" )?); - pb_adapter.set_message(format!("Enumerating resources for adapter {adapter}")); + pb_adapter_span.pb_set_message(format!("Enumerating resources for adapter {adapter}").as_str()); + let _ = pb_adapter_span.enter(); let adapter_resource = resources.get(&adapter).unwrap(); let adapter_type_name = adapter_resource.type_name.clone(); let manifest = import_manifest(adapter_resource.manifest.clone().unwrap())?; @@ -222,12 +214,9 @@ impl CommandDiscovery { } }; } - pb_adapter.finish_with_message(format!("Done with {adapter}")); debug!("Adapter '{}' listed {} matching resources", adapter_type_name, adapter_resources_count); } - - pb.finish_with_message("Discovery complete"); Ok(resources) } }