v0.1.4-pre.017
This commit is contained in:
428
crates/ksp-app-config-desk/src/logging_test.rs
Normal file
428
crates/ksp-app-config-desk/src/logging_test.rs
Normal file
@@ -0,0 +1,428 @@
|
||||
// file: crates/ksp-app-config-desk/src/logging_test.rs
|
||||
// version: 1
|
||||
|
||||
//! Controlled Logging test events for validating KSP runtime routing from Config Desk.
|
||||
|
||||
use ts_rs::TS; // rust-rules: derive-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<String>,
|
||||
/// 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(state: &crate::AppState, request: LoggingTestRequestDto) -> ksp_core_lib::Result<LoggingTestResultDto> {
|
||||
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<LoggingTestLevel> {
|
||||
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<LoggingTestTarget> {
|
||||
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<std::option::Option<String>> {
|
||||
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<std::option::Option<String>> {
|
||||
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<std::option::Option<String>> {
|
||||
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<T>(message: &str) -> ksp_core_lib::Result<T> {
|
||||
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;
|
||||
Reference in New Issue
Block a user