// file: crates/ksp-app-raw-transaction-ingest-desk/src/bootstrap.rs // version: 2 //! Config composite and Logging bootstrap for Raw Transaction Ingest Desk. /// Crate-internal Logging startup state shared by the application state. pub(crate) struct LoggingStartup { /// Guard that keeps the installed Logging runtime alive. pub(crate) guard: ksp_logging_lib::LoggingGuard, /// Active managed profile when Config resolved one successfully. pub(crate) active_profile_id: std::option::Option, /// Whether a transient in-memory fallback was installed. pub(crate) fallback_active: bool, /// Safe startup diagnostic retained for the shell. pub(crate) startup_diagnostic: std::option::Option, } enum LoggingStartupPlan { Managed { active_profile_id: String, settings: ksp_logging_lib::LoggingSettings, }, Fallback { initial_error: ksp_core_lib::Error, diagnostic: crate::CommandErrorDto, settings: ksp_logging_lib::LoggingSettings, }, } /// Builds the Config management facade from the common KSP CLI bootstrap contract. pub(crate) fn config_management(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result { let bootstrap = ksp_config_lib::ConfigBootstrapOptions::from_args(arguments); let bootstrap = match bootstrap { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let registry = ksp_config_lib::ConfigFileRegistry::from_args(arguments); let registry = match registry { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let engine = ksp_config_lib::ConfigDocumentEngine::new(bootstrap, registry); return std::result::Result::Ok(ksp_config_lib::ConfigManagement::new(engine)); } /// Loads the concrete Raw Transaction Ingest Desk Config composite using its registered logical `file_id` and autonomous default profile. pub(crate) fn load_raw_transaction_ingest_desk_composite( management: &ksp_config_lib::ConfigManagement, ) -> ksp_core_lib::Result { return crate::load_raw_transaction_ingest_desk_composite_profile(management, std::option::Option::None); } /// Loads one explicit or default Raw Transaction Ingest Desk composite profile by registered logical file identifier. pub(crate) fn load_raw_transaction_ingest_desk_composite_profile( management: &ksp_config_lib::ConfigManagement, requested_profile: std::option::Option<&str>, ) -> ksp_core_lib::Result { let file_id = ksp_config_lib::ConfigFileId::new(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK); let file_id = match file_id { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; return management.engine().load_resolved_composite(&file_id, requested_profile); } /// Returns one required standard profile from the Raw Transaction Ingest Desk composite after validating the referenced logical `file_id`. pub(crate) fn required_composite_component_profile( composite: &ksp_config_lib::ResolvedConfigComposite, component_id: &str, expected_file_id: &str, ) -> ksp_core_lib::Result { let component = composite.component(component_id); let component = match component { std::option::Option::Some(value) => value, std::option::Option::None => { return std::result::Result::Err( ksp_core_lib::Error::new(crate::ERROR_CODE_CONFIG_COMPOSITE_INVALID, "Raw Transaction Ingest Desk composite is missing a required component") .with_context("composite_file_id", composite.file_id().as_str()) .with_context("composite_profile_id", composite.profile_id()) .with_context("component_id", component_id), ); }, }; if component.resolved().file_id().as_str() != expected_file_id { return std::result::Result::Err( ksp_core_lib::Error::new( crate::ERROR_CODE_CONFIG_COMPOSITE_INVALID, "Raw Transaction Ingest Desk composite component references an unexpected Config document", ) .with_context("composite_file_id", composite.file_id().as_str()) .with_context("composite_profile_id", composite.profile_id()) .with_context("component_id", component_id) .with_context("expected_file_id", expected_file_id) .with_context("actual_file_id", component.resolved().file_id().as_str()), ); } return std::result::Result::Ok(component.resolved().clone()); } /// Initializes Logging from the Raw Transaction Ingest Desk composite, with a trace-level development fallback. pub(crate) fn initialize_logging( management: &ksp_config_lib::ConfigManagement, runtime_identity: &ksp_logging_lib::LoggingRuntimeIdentity, ) -> ksp_core_lib::Result { let plan = resolve_logging_startup(management); return match plan { LoggingStartupPlan::Managed { active_profile_id, settings } => { let guard = ksp_logging_lib::initialize_with_identity(&settings, runtime_identity); match guard { std::result::Result::Ok(guard) => { ksp_logging_lib::info!( target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_BOOTSTRAP, active_profile = active_profile_id.as_str(), "initialized Raw Transaction Ingest Desk logging from composite-managed configuration" ); std::result::Result::Ok(LoggingStartup { guard, active_profile_id: std::option::Option::Some(active_profile_id), fallback_active: false, startup_diagnostic: std::option::Option::None, }) }, std::result::Result::Err(error) => initialize_fallback_logging(error, runtime_identity), } }, LoggingStartupPlan::Fallback { initial_error, diagnostic, settings } => { initialize_planned_fallback_logging(initial_error, diagnostic, settings, runtime_identity) }, }; } fn fallback_logging_settings() -> ksp_logging_lib::LoggingSettings { return ksp_logging_lib::LoggingSettings::new( ksp_logging_lib::LogFilterLevel::Trace, ksp_logging_lib::SpanEvents::Off, std::option::Option::Some(ksp_logging_lib::ConsoleSettings::stderr()), std::vec::Vec::new(), ); } fn resolve_logging_startup(management: &ksp_config_lib::ConfigManagement) -> LoggingStartupPlan { let environment = ksp_config_lib::ConfigEnvironment::load(); let environment = match environment { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return fallback_startup_plan(error), }; let composite = crate::load_raw_transaction_ingest_desk_composite(management); let composite = match composite { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return fallback_startup_plan(error), }; let logging_profile = crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_LOGGING, ksp_config_lib::FILE_ID_STD_LOGGING); let logging_profile = match logging_profile { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return fallback_startup_plan(error), }; let transport_profile = crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_TRANSPORT, ksp_config_lib::FILE_ID_STD_TRANSPORT); if let std::result::Result::Err(error) = transport_profile { return fallback_startup_plan(error); } let store_profile = crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_STORE, ksp_config_lib::FILE_ID_STD_STORE); if let std::result::Result::Err(error) = store_profile { return fallback_startup_plan(error); } let resolved = management.engine().resolve_logging_config_profile(&logging_profile, &environment); let resolved = match resolved { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return fallback_startup_plan(error), }; return LoggingStartupPlan::Managed { active_profile_id: resolved.profile_id().to_owned(), settings: resolved.into_settings() }; } fn fallback_startup_plan(initial_error: ksp_core_lib::Error) -> LoggingStartupPlan { let diagnostic = crate::CommandErrorDto::from_error(&initial_error); return LoggingStartupPlan::Fallback { initial_error, diagnostic, settings: fallback_logging_settings() }; } fn initialize_fallback_logging( initial_error: ksp_core_lib::Error, runtime_identity: &ksp_logging_lib::LoggingRuntimeIdentity, ) -> ksp_core_lib::Result { let diagnostic = crate::CommandErrorDto::from_error(&initial_error); return initialize_planned_fallback_logging(initial_error, diagnostic, fallback_logging_settings(), runtime_identity); } fn initialize_planned_fallback_logging( initial_error: ksp_core_lib::Error, diagnostic: crate::CommandErrorDto, settings: ksp_logging_lib::LoggingSettings, runtime_identity: &ksp_logging_lib::LoggingRuntimeIdentity, ) -> ksp_core_lib::Result { let guard = ksp_logging_lib::initialize_with_identity(&settings, runtime_identity); let guard = match guard { std::result::Result::Ok(value) => value, std::result::Result::Err(fallback_error) => { return std::result::Result::Err( ksp_core_lib::Error::new(crate::ERROR_CODE_LOGGING_BOOTSTRAP_FAILED, "Cannot initialize Raw Transaction Ingest Desk fallback Logging runtime") .with_context("initial_error_domain", initial_error.code().domain()) .with_context("initial_error_code", initial_error.code().code()) .with_source(fallback_error), ); }, }; ksp_logging_lib::warn!( target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_BOOTSTRAP, error_domain = diagnostic.domain.as_str(), error_code = diagnostic.code.as_str(), "managed Logging configuration is unavailable; using transient trace-level development fallback" ); return std::result::Result::Ok(LoggingStartup { guard, active_profile_id: std::option::Option::None, fallback_active: true, startup_diagnostic: std::option::Option::Some(diagnostic), }); } #[cfg(test)] mod tests { #[test] fn development_fallback_keeps_trace_level_enabled() { let settings = super::fallback_logging_settings(); assert_eq!(settings.default_filter(), ksp_logging_lib::LogFilterLevel::Trace); } }