postfix-log-parser 0.2.0

高性能模块化Postfix日志解析器,经3.2GB生产数据验证,SMTPD事件100%准确率
Documentation
use super::common::add_troubleshooting_info;
use crate::events::relay::{ConnectionIssueType, DeliveryStatus, RelayConfigType, RelayEvent};
use serde_json::{json, Map, Value};

/// RELAY组件JSON格式化器
pub struct RelayJsonFormatter;

impl RelayJsonFormatter {
    pub fn new() -> Self {
        Self
    }

    /// 格式化RELAY事件为JSON
    pub fn format_event(&self, event: &RelayEvent) -> Value {
        let mut base_object = Map::new();

        // 添加组件通用信息
        base_object.insert("component".to_string(), json!("relay"));

        match event {
            RelayEvent::DeliveryStatus {
                base: _base,
                queue_id,
                recipient,
                relay_host,
                relay_ip,
                relay_port,
                delay,
                delays,
                dsn,
                status,
                status_description,
            } => {
                base_object.insert("event_type".to_string(), json!("delivery_status"));
                base_object.insert("queue_id".to_string(), json!(queue_id));
                base_object.insert("recipient".to_string(), json!(recipient));
                base_object.insert("relay_host".to_string(), json!(relay_host));
                base_object.insert("base".to_string(), json!(_base));
                if let Some(ip) = relay_ip {
                    base_object.insert("relay_ip".to_string(), json!(ip.to_string()));
                }

                if let Some(port) = relay_port {
                    base_object.insert("relay_port".to_string(), json!(port));
                }

                base_object.insert("delay_total_seconds".to_string(), json!(delay));

                // 详细的延迟分析
                let delay_details = json!({
                    "queue_wait_seconds": delays.queue_wait,
                    "connection_setup_seconds": delays.connection_setup,
                    "connection_time_seconds": delays.connection_time,
                    "transmission_time_seconds": delays.transmission_time,
                    "total_seconds": delays.total_delay(),
                    "performance_analysis": self.analyze_delays(delays)
                });
                base_object.insert("delay_breakdown".to_string(), delay_details);

                base_object.insert("dsn_code".to_string(), json!(dsn));
                base_object.insert(
                    "dsn_classification".to_string(),
                    json!(self.classify_dsn(dsn)),
                );
                base_object.insert("delivery_status".to_string(), json!(status));
                base_object.insert("status_description".to_string(), json!(status_description));

                // 添加状态分析
                base_object.insert(
                    "delivery_analysis".to_string(),
                    self.analyze_delivery_status(status, dsn, status_description),
                );

                // 添加中继健康评估
                base_object.insert(
                    "relay_health".to_string(),
                    self.assess_relay_health(relay_host, delay, status),
                );

                // 添加故障排除建议
                if matches!(
                    status,
                    DeliveryStatus::Deferred | DeliveryStatus::Failed | DeliveryStatus::Bounced
                ) {
                    add_troubleshooting_info(
                        &mut base_object,
                        &format!("relay delivery {} for {}", status, relay_host),
                    );
                }
            }

            RelayEvent::ConnectionIssue {
                base: _base,
                queue_id,
                recipient,
                relay_host,
                relay_ip,
                issue_type,
                error_message,
            } => {
                base_object.insert("event_type".to_string(), json!("connection_issue"));
                base_object.insert("queue_id".to_string(), json!(queue_id));
                base_object.insert("recipient".to_string(), json!(recipient));
                base_object.insert("relay_host".to_string(), json!(relay_host));
                base_object.insert("base".to_string(), json!(_base));
                if let Some(ip) = relay_ip {
                    base_object.insert("relay_ip".to_string(), json!(ip.to_string()));
                }

                base_object.insert("issue_type".to_string(), json!(issue_type));
                base_object.insert("error_message".to_string(), json!(error_message));

                // 添加连接问题分析
                base_object.insert(
                    "connection_analysis".to_string(),
                    self.analyze_connection_issue(issue_type, relay_host),
                );

                // 添加故障排除建议
                add_troubleshooting_info(
                    &mut base_object,
                    &format!("relay connection {} to {}", issue_type, relay_host),
                );
            }

            RelayEvent::RelayConfiguration {
                base: _base,
                config_type,
                details,
            } => {
                base_object.insert("event_type".to_string(), json!("relay_configuration"));
                base_object.insert("config_type".to_string(), json!(config_type));
                base_object.insert("config_details".to_string(), json!(details));
                base_object.insert("base".to_string(), json!(_base));
                // 添加配置分析
                base_object.insert(
                    "config_analysis".to_string(),
                    self.analyze_config_event(config_type, details),
                );
            }
        }

        // 添加组件统计信息
        base_object.insert(
            "relay_statistics".to_string(),
            self.get_relay_statistics(event),
        );

        Value::Object(base_object)
    }

    /// 分析延迟性能
    fn analyze_delays(&self, delays: &crate::events::relay::DelayBreakdown) -> Value {
        let total = delays.total_delay();
        let mut analysis = Map::new();

        // 性能评级
        let performance_rating = if total < 1.0 {
            "excellent"
        } else if total < 5.0 {
            "good"
        } else if total < 30.0 {
            "fair"
        } else {
            "poor"
        };

        analysis.insert("overall_rating".to_string(), json!(performance_rating));

        // 瓶颈分析
        let bottleneck = if delays.connection_time > total * 0.5 {
            "connection_establishment"
        } else if delays.transmission_time > total * 0.5 {
            "data_transmission"
        } else if delays.queue_wait > total * 0.5 {
            "queue_processing"
        } else {
            "balanced"
        };

        analysis.insert("primary_bottleneck".to_string(), json!(bottleneck));

        // 各阶段占比
        if total > 0.0 {
            analysis.insert(
                "phase_percentages".to_string(),
                json!({
                    "queue_wait": (delays.queue_wait / total * 100.0).round(),
                    "connection_setup": (delays.connection_setup / total * 100.0).round(),
                    "connection_time": (delays.connection_time / total * 100.0).round(),
                    "transmission_time": (delays.transmission_time / total * 100.0).round()
                }),
            );
        }

        Value::Object(analysis)
    }

    /// 分析投递状态
    fn analyze_delivery_status(
        &self,
        status: &DeliveryStatus,
        dsn: &str,
        _description: &str,
    ) -> Value {
        let mut analysis = Map::new();

        // 投递结果分类
        let result_category = match status {
            DeliveryStatus::Sent => "successful",
            DeliveryStatus::Deferred => "temporary_failure",
            DeliveryStatus::Bounced => "permanent_failure",
            DeliveryStatus::Failed => "permanent_failure",
            DeliveryStatus::Rejected => "permanent_failure",
        };

        analysis.insert("result_category".to_string(), json!(result_category));
        analysis.insert(
            "is_retryable".to_string(),
            json!(matches!(status, DeliveryStatus::Deferred)),
        );

        // DSN分析
        let dsn_class = self.classify_dsn(dsn);
        analysis.insert("dsn_class".to_string(), json!(dsn_class));

        // 建议操作
        let recommended_action = match status {
            DeliveryStatus::Sent => "none",
            DeliveryStatus::Deferred => "monitor_retry",
            DeliveryStatus::Bounced => "check_recipient_address",
            DeliveryStatus::Failed => "investigate_server_config",
            DeliveryStatus::Rejected => "verify_sender_reputation",
        };

        analysis.insert("recommended_action".to_string(), json!(recommended_action));

        Value::Object(analysis)
    }

    /// 评估中继健康状况
    fn assess_relay_health(&self, relay_host: &str, delay: &f64, status: &DeliveryStatus) -> Value {
        let mut health = Map::new();

        // 性能健康度
        let performance_score = if *delay < 1.0 {
            100
        } else if *delay < 5.0 {
            80
        } else if *delay < 30.0 {
            60
        } else {
            30
        };

        // 可靠性健康度
        let reliability_score = match status {
            DeliveryStatus::Sent => 100,
            DeliveryStatus::Deferred => 70,
            DeliveryStatus::Bounced => 30,
            DeliveryStatus::Failed => 20,
            DeliveryStatus::Rejected => 20,
        };

        let overall_score = (performance_score + reliability_score) / 2;

        let health_status = if overall_score >= 90 {
            "excellent"
        } else if overall_score >= 70 {
            "good"
        } else if overall_score >= 50 {
            "warning"
        } else {
            "critical"
        };

        health.insert("relay_host".to_string(), json!(relay_host));
        health.insert("performance_score".to_string(), json!(performance_score));
        health.insert("reliability_score".to_string(), json!(reliability_score));
        health.insert("overall_score".to_string(), json!(overall_score));
        health.insert("health_status".to_string(), json!(health_status));

        Value::Object(health)
    }

    /// 分析连接问题
    fn analyze_connection_issue(
        &self,
        issue_type: &ConnectionIssueType,
        relay_host: &str,
    ) -> Value {
        let mut analysis = Map::new();

        let (severity, likely_cause, resolution_time) = match issue_type {
            ConnectionIssueType::LostConnection => {
                ("medium", "network_instability", "5-30 minutes")
            }
            ConnectionIssueType::ConnectionTimeout => {
                ("medium", "network_congestion", "5-60 minutes")
            }
            ConnectionIssueType::ConnectionRefused => {
                ("high", "service_unavailable", "immediate to hours")
            }
            ConnectionIssueType::DnsResolutionFailed => {
                ("high", "dns_configuration", "immediate to hours")
            }
            ConnectionIssueType::TlsHandshakeFailed => {
                ("high", "certificate_issue", "immediate to days")
            }
            ConnectionIssueType::AuthenticationFailed => ("high", "credential_issue", "immediate"),
            ConnectionIssueType::Other => ("medium", "unknown", "varies"),
        };

        analysis.insert("severity".to_string(), json!(severity));
        analysis.insert("likely_cause".to_string(), json!(likely_cause));
        analysis.insert(
            "expected_resolution_time".to_string(),
            json!(resolution_time),
        );
        analysis.insert("affected_relay".to_string(), json!(relay_host));

        Value::Object(analysis)
    }

    /// 分析配置事件
    fn analyze_config_event(&self, config_type: &RelayConfigType, details: &str) -> Value {
        let mut analysis = Map::new();

        let importance = match config_type {
            RelayConfigType::RelayHostConfig => "critical",
            RelayConfigType::TransportMapping => "high",
            RelayConfigType::AuthConfig => "high",
            RelayConfigType::TlsConfig => "medium",
        };

        analysis.insert("importance".to_string(), json!(importance));
        analysis.insert("config_type".to_string(), json!(config_type));
        analysis.insert(
            "requires_attention".to_string(),
            json!(details.contains("error") || details.contains("warning")),
        );

        Value::Object(analysis)
    }

    /// DSN代码分类
    fn classify_dsn(&self, dsn: &str) -> &'static str {
        if dsn.starts_with("2.") {
            "success"
        } else if dsn.starts_with("4.") {
            "temporary_failure"
        } else if dsn.starts_with("5.") {
            "permanent_failure"
        } else {
            "unknown"
        }
    }

    /// 获取中继统计信息
    fn get_relay_statistics(&self, event: &RelayEvent) -> Value {
        let mut stats = Map::new();

        stats.insert("component".to_string(), json!("relay"));
        stats.insert(
            "component_description".to_string(),
            json!("Postfix中继传输代理"),
        );

        match event {
            RelayEvent::DeliveryStatus {
                relay_host, status, ..
            } => {
                stats.insert("relay_destination".to_string(), json!(relay_host));
                stats.insert("operation_type".to_string(), json!("mail_delivery"));
                stats.insert("operation_result".to_string(), json!(status));
            }
            RelayEvent::ConnectionIssue {
                relay_host,
                issue_type,
                ..
            } => {
                stats.insert("relay_destination".to_string(), json!(relay_host));
                stats.insert("operation_type".to_string(), json!("connection"));
                stats.insert("operation_result".to_string(), json!(issue_type));
            }
            RelayEvent::RelayConfiguration { config_type, .. } => {
                stats.insert("operation_type".to_string(), json!("configuration"));
                stats.insert("config_category".to_string(), json!(config_type));
            }
        }

        Value::Object(stats)
    }
}

impl Default for RelayJsonFormatter {
    fn default() -> Self {
        Self::new()
    }
}