// file: crates/ksp-app-config-desk/src/logging_test.rs // version: 2 //! Controlled Logging test events for validating KSP runtime routing from Config Desk. use ts_rs::TS; // rust-rules: trait-import /// Controlled request emitted through the backend KSP Logging facade. #[derive(Clone, Debug, serde::Deserialize, TS)] #[serde(rename_all = "camelCase")] #[ts(export, export_to = "../frontend/ts/bindings/ksp_app_config_desk/logging_test/LoggingTestRequestDto.ts")] pub(crate) struct LoggingTestRequestDto { /// Requested level: trace/debug/info/warn/error/all. pub(crate) level: String, /// Controlled backend target identifier. pub(crate) target_id: String, /// Domain selection mode: absent/known/custom. pub(crate) domain_mode: String, /// Selected known domain or custom domain token. pub(crate) domain: String, /// Human test message emitted as the event body. pub(crate) message: String, } /// Safe result metadata for one controlled backend Logging test request. #[derive(Clone, Debug, serde::Serialize, TS)] #[serde(rename_all = "camelCase")] #[ts(export, export_to = "../frontend/ts/bindings/ksp_app_config_desk/logging_test/LoggingTestResultDto.ts")] pub(crate) struct LoggingTestResultDto { /// Number of Logging events emitted by the request. pub(crate) emitted_event_count: u32, /// Requested level selector. pub(crate) requested_level: String, /// Effective static KSP target used by the emitted events. pub(crate) target: String, /// Effective domain, or `None` when domain routing is intentionally absent. pub(crate) domain: std::option::Option, /// Logging runtime generation active while the events were emitted. pub(crate) logging_generation: u32, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum LoggingTestLevel { Trace, Debug, Info, Warn, Error, All, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum LoggingTestTarget { App, Dedicated, } /// Emits one controlled backend test request through `ksp-logging-lib` only. pub(crate) fn emit_logging_test(state: &crate::AppState, request: LoggingTestRequestDto) -> ksp_core_lib::Result { let level = parse_level(request.level.as_str()); let level = match level { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let target = parse_target(request.target_id.as_str()); let target = match target { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let domain = resolve_domain(request.domain_mode.as_str(), request.domain.as_str()); let domain = match domain { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let message = validate_message(request.message.as_str()); let message = match message { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let runtime_status = state.logging_runtime_status(); let runtime_status = match runtime_status { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let emitted_event_count = emit_levels(level, target, domain.as_deref(), message); return std::result::Result::Ok(LoggingTestResultDto { emitted_event_count, requested_level: request.level.trim().to_ascii_lowercase(), target: target_value(target).to_owned(), domain, logging_generation: runtime_status.generation, }); } fn parse_level(level: &str) -> ksp_core_lib::Result { return match level.trim().to_ascii_lowercase().as_str() { "trace" => std::result::Result::Ok(LoggingTestLevel::Trace), "debug" => std::result::Result::Ok(LoggingTestLevel::Debug), "info" => std::result::Result::Ok(LoggingTestLevel::Info), "warn" => std::result::Result::Ok(LoggingTestLevel::Warn), "error" => std::result::Result::Ok(LoggingTestLevel::Error), "all" => std::result::Result::Ok(LoggingTestLevel::All), _ => invalid_request("Logging test level is not supported"), }; } fn parse_target(target_id: &str) -> ksp_core_lib::Result { return match target_id.trim().to_ascii_lowercase().as_str() { "app" => std::result::Result::Ok(LoggingTestTarget::App), "logging_test" => std::result::Result::Ok(LoggingTestTarget::Dedicated), _ => invalid_request("Logging test target is not supported"), }; } fn resolve_domain(domain_mode: &str, domain: &str) -> ksp_core_lib::Result> { return match domain_mode.trim().to_ascii_lowercase().as_str() { "absent" => std::result::Result::Ok(std::option::Option::None), "known" => resolve_known_domain(domain), "custom" => resolve_custom_domain(domain), _ => invalid_request("Logging test domain mode is not supported"), }; } fn resolve_known_domain(domain: &str) -> ksp_core_lib::Result> { return match domain.trim() { crate::TRACING_DOMAIN_LOGGING_TEST | crate::TRACING_DOMAIN_LOGGING_RUNTIME | crate::TRACING_DOMAIN_FRONTEND => { std::result::Result::Ok(std::option::Option::Some(domain.trim().to_owned())) }, _ => invalid_request("Logging test known domain is not supported"), }; } fn resolve_custom_domain(domain: &str) -> ksp_core_lib::Result> { let domain = domain.trim(); if domain.is_empty() || domain.len() > 80 || !domain.chars().all(is_domain_character) { return invalid_request("Logging test custom domain is invalid"); } return std::result::Result::Ok(std::option::Option::Some(domain.to_owned())); } fn is_domain_character(character: char) -> bool { return character.is_ascii_alphanumeric() || character == '.' || character == '_' || character == '-'; } fn validate_message(message: &str) -> ksp_core_lib::Result<&str> { let message = message.trim(); if message.is_empty() || message.len() > 500 { return invalid_request("Logging test message must contain between 1 and 500 bytes"); } return std::result::Result::Ok(message); } fn invalid_request(message: &str) -> ksp_core_lib::Result { return std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_LOGGING_TEST_REQUEST_INVALID, message)); } const fn target_value(target: LoggingTestTarget) -> &'static str { return match target { LoggingTestTarget::App => crate::TRACING_TARGET, LoggingTestTarget::Dedicated => crate::TRACING_TARGET_LOGGING_TEST, }; } fn emit_levels(level: LoggingTestLevel, target: LoggingTestTarget, domain: std::option::Option<&str>, message: &str) -> u32 { return match level { LoggingTestLevel::Trace => { emit_one(LoggingTestLevel::Trace, target, domain, message); 1 }, LoggingTestLevel::Debug => { emit_one(LoggingTestLevel::Debug, target, domain, message); 1 }, LoggingTestLevel::Info => { emit_one(LoggingTestLevel::Info, target, domain, message); 1 }, LoggingTestLevel::Warn => { emit_one(LoggingTestLevel::Warn, target, domain, message); 1 }, LoggingTestLevel::Error => { emit_one(LoggingTestLevel::Error, target, domain, message); 1 }, LoggingTestLevel::All => { emit_one(LoggingTestLevel::Trace, target, domain, message); emit_one(LoggingTestLevel::Debug, target, domain, message); emit_one(LoggingTestLevel::Info, target, domain, message); emit_one(LoggingTestLevel::Warn, target, domain, message); emit_one(LoggingTestLevel::Error, target, domain, message); 5 }, }; } fn emit_one(level: LoggingTestLevel, target: LoggingTestTarget, domain: std::option::Option<&str>, message: &str) { return match target { LoggingTestTarget::App => emit_app_target(level, domain, message), LoggingTestTarget::Dedicated => emit_dedicated_target(level, domain, message), }; } fn emit_app_target(level: LoggingTestLevel, domain: std::option::Option<&str>, message: &str) { return match level { LoggingTestLevel::Trace => emit_app_trace(domain, message), LoggingTestLevel::Debug => emit_app_debug(domain, message), LoggingTestLevel::Info => emit_app_info(domain, message), LoggingTestLevel::Warn => emit_app_warn(domain, message), LoggingTestLevel::Error => emit_app_error(domain, message), LoggingTestLevel::All => (), }; } fn emit_dedicated_target(level: LoggingTestLevel, domain: std::option::Option<&str>, message: &str) { return match level { LoggingTestLevel::Trace => emit_dedicated_trace(domain, message), LoggingTestLevel::Debug => emit_dedicated_debug(domain, message), LoggingTestLevel::Info => emit_dedicated_info(domain, message), LoggingTestLevel::Warn => emit_dedicated_warn(domain, message), LoggingTestLevel::Error => emit_dedicated_error(domain, message), LoggingTestLevel::All => (), }; } fn emit_app_trace(domain: std::option::Option<&str>, message: &str) { return match domain { std::option::Option::Some(domain) => ksp_logging_lib::trace!( target: crate::TRACING_TARGET, domain = domain, action = "logging_test", test_source = "backend", test_level = "trace", "{message}" ), std::option::Option::None => ksp_logging_lib::trace!( target: crate::TRACING_TARGET, action = "logging_test", test_source = "backend", test_level = "trace", "{message}" ), }; } fn emit_app_debug(domain: std::option::Option<&str>, message: &str) { return match domain { std::option::Option::Some(domain) => ksp_logging_lib::debug!( target: crate::TRACING_TARGET, domain = domain, action = "logging_test", test_source = "backend", test_level = "debug", "{message}" ), std::option::Option::None => ksp_logging_lib::debug!( target: crate::TRACING_TARGET, action = "logging_test", test_source = "backend", test_level = "debug", "{message}" ), }; } fn emit_app_info(domain: std::option::Option<&str>, message: &str) { return match domain { std::option::Option::Some(domain) => ksp_logging_lib::info!( target: crate::TRACING_TARGET, domain = domain, action = "logging_test", test_source = "backend", test_level = "info", "{message}" ), std::option::Option::None => ksp_logging_lib::info!( target: crate::TRACING_TARGET, action = "logging_test", test_source = "backend", test_level = "info", "{message}" ), }; } fn emit_app_warn(domain: std::option::Option<&str>, message: &str) { return match domain { std::option::Option::Some(domain) => ksp_logging_lib::warn!( target: crate::TRACING_TARGET, domain = domain, action = "logging_test", test_source = "backend", test_level = "warn", "{message}" ), std::option::Option::None => ksp_logging_lib::warn!( target: crate::TRACING_TARGET, action = "logging_test", test_source = "backend", test_level = "warn", "{message}" ), }; } fn emit_app_error(domain: std::option::Option<&str>, message: &str) { return match domain { std::option::Option::Some(domain) => ksp_logging_lib::error!( target: crate::TRACING_TARGET, domain = domain, action = "logging_test", test_source = "backend", test_level = "error", "{message}" ), std::option::Option::None => ksp_logging_lib::error!( target: crate::TRACING_TARGET, action = "logging_test", test_source = "backend", test_level = "error", "{message}" ), }; } fn emit_dedicated_trace(domain: std::option::Option<&str>, message: &str) { return match domain { std::option::Option::Some(domain) => ksp_logging_lib::trace!( target: crate::TRACING_TARGET_LOGGING_TEST, domain = domain, action = "logging_test", test_source = "backend", test_level = "trace", "{message}" ), std::option::Option::None => ksp_logging_lib::trace!( target: crate::TRACING_TARGET_LOGGING_TEST, action = "logging_test", test_source = "backend", test_level = "trace", "{message}" ), }; } fn emit_dedicated_debug(domain: std::option::Option<&str>, message: &str) { return match domain { std::option::Option::Some(domain) => ksp_logging_lib::debug!( target: crate::TRACING_TARGET_LOGGING_TEST, domain = domain, action = "logging_test", test_source = "backend", test_level = "debug", "{message}" ), std::option::Option::None => ksp_logging_lib::debug!( target: crate::TRACING_TARGET_LOGGING_TEST, action = "logging_test", test_source = "backend", test_level = "debug", "{message}" ), }; } fn emit_dedicated_info(domain: std::option::Option<&str>, message: &str) { return match domain { std::option::Option::Some(domain) => ksp_logging_lib::info!( target: crate::TRACING_TARGET_LOGGING_TEST, domain = domain, action = "logging_test", test_source = "backend", test_level = "info", "{message}" ), std::option::Option::None => ksp_logging_lib::info!( target: crate::TRACING_TARGET_LOGGING_TEST, action = "logging_test", test_source = "backend", test_level = "info", "{message}" ), }; } fn emit_dedicated_warn(domain: std::option::Option<&str>, message: &str) { return match domain { std::option::Option::Some(domain) => ksp_logging_lib::warn!( target: crate::TRACING_TARGET_LOGGING_TEST, domain = domain, action = "logging_test", test_source = "backend", test_level = "warn", "{message}" ), std::option::Option::None => ksp_logging_lib::warn!( target: crate::TRACING_TARGET_LOGGING_TEST, action = "logging_test", test_source = "backend", test_level = "warn", "{message}" ), }; } fn emit_dedicated_error(domain: std::option::Option<&str>, message: &str) { return match domain { std::option::Option::Some(domain) => ksp_logging_lib::error!( target: crate::TRACING_TARGET_LOGGING_TEST, domain = domain, action = "logging_test", test_source = "backend", test_level = "error", "{message}" ), std::option::Option::None => ksp_logging_lib::error!( target: crate::TRACING_TARGET_LOGGING_TEST, action = "logging_test", test_source = "backend", test_level = "error", "{message}" ), }; } #[cfg(test)] #[path = "../unit_tests/logging_test.rs"] mod tests;