athena_rs 3.23.0

Hyper performant polyglot Database driver
Documentation
//! Logging-client schema diagnostics report builder.
//!
//! This module preserves a stable report-building entrypoint while intermediate
//! diagnostics pipeline staging is delegated to
//! `debug_report_stage_input_assembly`,
//! `debug_report_stage_output_assembly`, and final payload projection/sorting
//! assembly is delegated to `debug_report_from_stage_output_assembly` (which
//! delegates to `debug_report_stage_output_handoff_assembly`).

use super::debug_contracts::LoggingSchemaDebugReport;
use super::debug_report_from_stage_output_assembly::build_logging_schema_debug_report_from_stage_output_assembly;
use super::debug_report_input_contracts::LoggingSchemaDebugReportBuilderInput;
use super::debug_report_stage_input_assembly::build_debug_report_stage_input_assembly;
use super::debug_report_stage_output_assembly::build_debug_report_stage_output_assembly;

/// Builds a logging-client schema diagnostics report from one typed builder input payload.
pub fn build_logging_schema_debug_report_from_input(
    input: LoggingSchemaDebugReportBuilderInput,
) -> LoggingSchemaDebugReport {
    let stage_input = build_debug_report_stage_input_assembly(input);
    let stage = build_debug_report_stage_output_assembly(stage_input);
    build_logging_schema_debug_report_from_stage_output_assembly(stage)
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::api::schema::debug_contracts::LoggingSchemaDebugReport;
    use crate::api::schema::debug_report_test_fixtures::{
        build_expected_logging_schema_columns_for_tests,
        build_expected_logging_schema_relations_for_tests,
    };

    /// Asserts summary counters remain consistent with canonical report payload lists.
    fn assert_summary_matches_report_payload(report: &LoggingSchemaDebugReport) {
        let found_table_count = report
            .expected_tables
            .iter()
            .filter(|row| row.found)
            .count();

        assert_eq!(
            report.summary.expected_table_count,
            report.expected_tables.len()
        );
        assert_eq!(report.summary.found_table_count, found_table_count);
        assert_eq!(
            report.summary.required_missing_table_count,
            report.still_needed.required_missing_tables.len()
        );
        assert_eq!(
            report.summary.optional_missing_table_count,
            report.still_needed.optional_missing_tables.len()
        );
        assert_eq!(
            report.summary.required_missing_column_count,
            report.still_needed.required_missing_columns.len()
        );
        assert_eq!(
            report.summary.optional_missing_column_count,
            report.still_needed.optional_missing_columns.len()
        );
        assert_eq!(
            report.summary.relation_type_mismatch_count,
            report.still_needed.relation_type_mismatches.len()
        );
        assert_eq!(
            report.missing_required_tables,
            report.still_needed.required_missing_tables
        );
        assert_eq!(
            report.missing_optional_tables,
            report.still_needed.optional_missing_tables
        );
    }

    #[test]
    /// Ensures a fully present expected schema yields `healthy`.
    fn report_is_healthy_when_every_expected_table_and_column_exists() {
        let report =
            build_logging_schema_debug_report_from_input(LoggingSchemaDebugReportBuilderInput {
                logging_client: "athena_logging".to_string(),
                relations: build_expected_logging_schema_relations_for_tests(true),
                columns: build_expected_logging_schema_columns_for_tests(true),
            });

        assert_summary_matches_report_payload(&report);
        assert_eq!(report.summary.health, "healthy");
        assert_eq!(report.summary.required_missing_table_count, 0);
        assert_eq!(report.summary.optional_missing_table_count, 0);
        assert_eq!(report.summary.required_missing_column_count, 0);
        assert_eq!(report.summary.optional_missing_column_count, 0);
        assert_eq!(report.summary.relation_type_mismatch_count, 0);
        assert!(report.still_needed.required_missing_tables.is_empty());
        assert!(report.still_needed.optional_missing_tables.is_empty());
        assert!(report.still_needed.required_missing_columns.is_empty());
        assert!(report.still_needed.optional_missing_columns.is_empty());
        assert!(report.still_needed.relation_type_mismatches.is_empty());
    }

    #[test]
    /// Ensures missing only optional expected tables yields `warning`.
    fn report_is_warning_when_only_optional_tables_are_missing() {
        let report =
            build_logging_schema_debug_report_from_input(LoggingSchemaDebugReportBuilderInput {
                logging_client: "athena_logging".to_string(),
                relations: build_expected_logging_schema_relations_for_tests(false),
                columns: build_expected_logging_schema_columns_for_tests(false),
            });

        assert_summary_matches_report_payload(&report);
        assert_eq!(report.summary.health, "warning");
        assert_eq!(report.summary.required_missing_table_count, 0);
        assert!(report.summary.optional_missing_table_count >= 1);
        assert_eq!(report.summary.required_missing_column_count, 0);
        assert!(report.still_needed.required_missing_tables.is_empty());
        assert!(!report.still_needed.optional_missing_tables.is_empty());
        assert_eq!(
            report.missing_required_tables,
            report.still_needed.required_missing_tables
        );
        assert_eq!(
            report.missing_optional_tables,
            report.still_needed.optional_missing_tables
        );
    }

    #[test]
    /// Ensures missing a required expected table yields `degraded`.
    fn report_is_degraded_when_a_required_table_is_missing() {
        let mut relations = build_expected_logging_schema_relations_for_tests(true);
        relations.retain(|entry| entry.table_name != "gateway_request_log");
        let mut columns = build_expected_logging_schema_columns_for_tests(true);
        columns.retain(|entry| entry.table_name != "gateway_request_log");

        let report =
            build_logging_schema_debug_report_from_input(LoggingSchemaDebugReportBuilderInput {
                logging_client: "athena_logging".to_string(),
                relations,
                columns,
            });

        assert_summary_matches_report_payload(&report);
        assert_eq!(report.summary.health, "degraded");
        assert_eq!(report.summary.required_missing_table_count, 1);
        assert!(!report.missing_required_tables.is_empty());
        assert!(!report.still_needed.required_missing_tables.is_empty());
        assert!(!report.still_needed.required_missing_columns.is_empty());
        assert_eq!(
            report.missing_required_tables,
            report.still_needed.required_missing_tables
        );
        assert_eq!(
            report.missing_optional_tables,
            report.still_needed.optional_missing_tables
        );
    }
}