// file: crates/ksp-app-wallet-desk/src/frontend_logging.rs // version: 1 //! KSP-owned bridge for technical log events emitted by Wallet Desk frontend scripts. use ts_rs::TS; // rust-rules: trait-import /// Log payload sent by Wallet Desk frontend scripts. #[derive(Clone, Debug, serde::Deserialize, TS)] #[serde(rename_all = "camelCase")] #[ts(export, export_to = "../frontend/ts/bindings/ksp_app_wallet_desk/frontend_logging/FrontendLogPayloadDto.ts")] pub(crate) struct FrontendLogPayloadDto { /// Lowercase KSP log level. pub(crate) level: String, /// Whitelisted logical frontend target identifier. pub(crate) target_id: String, /// Rendered technical frontend message. pub(crate) message: String, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum FrontendLogLevel { Debug, Error, Info, Trace, Warn, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum FrontendLogTarget { Frontend, Main, Splash, } /// Emits one validated frontend event through the KSP Logging facade. pub(crate) fn emit_frontend_log_event(payload: FrontendLogPayloadDto) -> ksp_core_lib::Result<()> { let level = parse_level(payload.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(payload.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), }; emit_validated_frontend_log(level, target, payload.message.as_str()); return std::result::Result::Ok(()); } fn parse_level(level: &str) -> ksp_core_lib::Result { return match level.trim().to_ascii_lowercase().as_str() { "debug" => std::result::Result::Ok(FrontendLogLevel::Debug), "error" => std::result::Result::Ok(FrontendLogLevel::Error), "info" => std::result::Result::Ok(FrontendLogLevel::Info), "trace" => std::result::Result::Ok(FrontendLogLevel::Trace), "warn" => std::result::Result::Ok(FrontendLogLevel::Warn), _ => std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_FRONTEND_LOG_LEVEL_INVALID, "Frontend log level is not supported")), }; } fn parse_target(target_id: &str) -> ksp_core_lib::Result { return match target_id.trim().to_ascii_lowercase().as_str() { "frontend" => std::result::Result::Ok(FrontendLogTarget::Frontend), "main" => std::result::Result::Ok(FrontendLogTarget::Main), "splash" => std::result::Result::Ok(FrontendLogTarget::Splash), _ => { std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_FRONTEND_LOG_TARGET_INVALID, "Frontend log target identifier is not supported")) }, }; } fn emit_validated_frontend_log(level: FrontendLogLevel, target: FrontendLogTarget, message: &str) { return match target { FrontendLogTarget::Frontend => emit_frontend_target(level, message), FrontendLogTarget::Main => emit_main_target(level, message), FrontendLogTarget::Splash => emit_splash_target(level, message), }; } fn emit_frontend_target(level: FrontendLogLevel, message: &str) { return match level { FrontendLogLevel::Debug => { ksp_logging_lib::debug!(target: crate::TRACING_TARGET_FRONTEND, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "frontend", "{message}") }, FrontendLogLevel::Error => { ksp_logging_lib::error!(target: crate::TRACING_TARGET_FRONTEND, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "frontend", "{message}") }, FrontendLogLevel::Info => { ksp_logging_lib::info!(target: crate::TRACING_TARGET_FRONTEND, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "frontend", "{message}") }, FrontendLogLevel::Trace => { ksp_logging_lib::trace!(target: crate::TRACING_TARGET_FRONTEND, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "frontend", "{message}") }, FrontendLogLevel::Warn => { ksp_logging_lib::warn!(target: crate::TRACING_TARGET_FRONTEND, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "frontend", "{message}") }, }; } fn emit_main_target(level: FrontendLogLevel, message: &str) { return match level { FrontendLogLevel::Debug => { ksp_logging_lib::debug!(target: crate::TRACING_TARGET_FRONTEND_MAIN, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "main", "{message}") }, FrontendLogLevel::Error => { ksp_logging_lib::error!(target: crate::TRACING_TARGET_FRONTEND_MAIN, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "main", "{message}") }, FrontendLogLevel::Info => { ksp_logging_lib::info!(target: crate::TRACING_TARGET_FRONTEND_MAIN, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "main", "{message}") }, FrontendLogLevel::Trace => { ksp_logging_lib::trace!(target: crate::TRACING_TARGET_FRONTEND_MAIN, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "main", "{message}") }, FrontendLogLevel::Warn => { ksp_logging_lib::warn!(target: crate::TRACING_TARGET_FRONTEND_MAIN, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "main", "{message}") }, }; } fn emit_splash_target(level: FrontendLogLevel, message: &str) { return match level { FrontendLogLevel::Debug => { ksp_logging_lib::debug!(target: crate::TRACING_TARGET_FRONTEND_SPLASH, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "splash", "{message}") }, FrontendLogLevel::Error => { ksp_logging_lib::error!(target: crate::TRACING_TARGET_FRONTEND_SPLASH, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "splash", "{message}") }, FrontendLogLevel::Info => { ksp_logging_lib::info!(target: crate::TRACING_TARGET_FRONTEND_SPLASH, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "splash", "{message}") }, FrontendLogLevel::Trace => { ksp_logging_lib::trace!(target: crate::TRACING_TARGET_FRONTEND_SPLASH, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "splash", "{message}") }, FrontendLogLevel::Warn => { ksp_logging_lib::warn!(target: crate::TRACING_TARGET_FRONTEND_SPLASH, domain = crate::TRACING_DOMAIN_FRONTEND, action = "frontend_log", target_id = "splash", "{message}") }, }; } #[cfg(test)] #[path = "../unit_tests/frontend_logging.rs"] mod tests;