postfix-log-parser 0.2.0

高性能模块化Postfix日志解析器,经3.2GB生产数据验证,SMTPD事件100%准确率
Documentation
use super::LogFormatter;
use crate::events::ComponentEvent;
use crate::parsing::ParseResult;
use serde_json;
use std::error::Error;

pub mod cleanup;
pub mod common;
pub mod discard;
pub mod error;
pub mod postfix_script;
pub mod postsuper;
pub mod qmgr;
pub mod relay;
pub mod smtp;
pub mod smtpd;

pub use cleanup::format_cleanup_event;
pub use common::*;
pub use discard::DiscardJsonFormatter;
pub use error::ErrorJsonFormatter;
pub use postfix_script::format_postfix_script_event;
pub use postsuper::format_postsuper_event;
pub use qmgr::format_qmgr_event;
pub use relay::RelayJsonFormatter;
pub use smtp::format_smtp_event;
pub use smtpd::format_smtpd_event;

/// JSON格式化器
pub struct JsonFormatter;

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

impl LogFormatter for JsonFormatter {
    fn format_single(
        &self,
        line_number: usize,
        line: &str,
        result: &ParseResult,
    ) -> Result<String, Box<dyn Error>> {
        let mut parsed_data = serde_json::Map::new();

        // 基础字段
        parsed_data.insert(
            "line_number".to_string(),
            serde_json::Value::Number(serde_json::Number::from(line_number)),
        );
        parsed_data.insert(
            "original_line".to_string(),
            serde_json::Value::String(line.to_string()),
        );
        parsed_data.insert(
            "confidence".to_string(),
            serde_json::Value::Number(
                serde_json::Number::from_f64(result.confidence as f64).unwrap(),
            ),
        );

        if let Some(event) = &result.event {
            // 事件相关字段
            parsed_data.insert(
                "timestamp".to_string(),
                serde_json::Value::String(event.timestamp.to_rfc3339()),
            );
            parsed_data.insert(
                "hostname".to_string(),
                serde_json::Value::String(event.hostname.clone()),
            );
            parsed_data.insert(
                "component".to_string(),
                serde_json::Value::String(event.component.clone()),
            );
            parsed_data.insert(
                "process_id".to_string(),
                serde_json::Value::Number(serde_json::Number::from(event.process_id)),
            );
            parsed_data.insert(
                "log_level".to_string(),
                serde_json::Value::String(format!("{:?}", event.log_level)),
            );

            if let Some(queue_id) = &event.queue_id {
                parsed_data.insert(
                    "queue_id".to_string(),
                    serde_json::Value::String(queue_id.clone()),
                );
            }

            // 处理具体事件类型
            match &event.event {
                ComponentEvent::Smtpd(smtpd_event) => {
                    let event_data = format_smtpd_event(smtpd_event);
                    for (key, value) in event_data {
                        parsed_data.insert(key, value);
                    }
                }
                ComponentEvent::Smtp(smtp_event) => {
                    let event_data = format_smtp_event(smtp_event);
                    for (key, value) in event_data {
                        parsed_data.insert(key, value);
                    }
                }
                ComponentEvent::Qmgr(qmgr_event) => {
                    let event_data = format_qmgr_event(qmgr_event);
                    for (key, value) in event_data {
                        parsed_data.insert(key, value);
                    }
                }
                ComponentEvent::Cleanup(cleanup_event) => {
                    let event_data = format_cleanup_event(cleanup_event);
                    if let serde_json::Value::Object(map) = event_data {
                        for (key, value) in map {
                            parsed_data.insert(key, value);
                        }
                    }
                }
                ComponentEvent::Error(error_event) => {
                    let event_data = ErrorJsonFormatter::format_error_event(error_event);
                    if let serde_json::Value::Object(map) = event_data {
                        for (key, value) in map {
                            parsed_data.insert(key, value);
                        }
                    }
                }
                ComponentEvent::Relay(relay_event) => {
                    let event_data = RelayJsonFormatter::new().format_event(relay_event);
                    if let serde_json::Value::Object(map) = event_data {
                        for (key, value) in map {
                            parsed_data.insert(key, value);
                        }
                    }
                }
                ComponentEvent::Discard(discard_event) => {
                    let event_data = DiscardJsonFormatter::new().format_event(discard_event);
                    if let serde_json::Value::Object(map) = event_data {
                        for (key, value) in map {
                            parsed_data.insert(key, value);
                        }
                    }
                }
                ComponentEvent::PostfixScript(postfix_script_event) => {
                    let event_data = format_postfix_script_event(postfix_script_event);
                    if let serde_json::Value::Object(map) = event_data {
                        for (key, value) in map {
                            parsed_data.insert(key, value);
                        }
                    }
                }
                ComponentEvent::Postsuper(postsuper_event) => {
                    let event_data = format_postsuper_event(postsuper_event);
                    if let serde_json::Value::Object(map) = event_data {
                        for (key, value) in map {
                            parsed_data.insert(key, value);
                        }
                    }
                }
                ComponentEvent::Unknown(unknown_event) => {
                    parsed_data.insert(
                        "event_type".to_string(),
                        serde_json::Value::String("unknown".to_string()),
                    );
                    parsed_data.insert(
                        "message".to_string(),
                        serde_json::Value::String(unknown_event.message.clone()),
                    );
                }
                _ => {
                    parsed_data.insert(
                        "event_type".to_string(),
                        serde_json::Value::String("other".to_string()),
                    );
                    parsed_data.insert(
                        "message".to_string(),
                        serde_json::Value::String(format!("{:?}", event.event)),
                    );
                }
            }
        } else {
            // 解析失败的情况
            parsed_data.insert(
                "error".to_string(),
                serde_json::Value::String("parse_failed".to_string()),
            );
            if !result.parsing_errors.is_empty() {
                parsed_data.insert(
                    "error_details".to_string(),
                    serde_json::Value::String(format!("{:?}", result.parsing_errors[0])),
                );
            }
        }

        Ok(serde_json::to_string(&serde_json::Value::Object(
            parsed_data,
        ))?)
    }

    fn format_multiple(
        &self,
        results: Vec<(usize, String, ParseResult)>,
    ) -> Result<String, Box<dyn Error>> {
        let mut json_objects = Vec::new();

        for (line_number, line, result) in results {
            let json_str = self.format_single(line_number, &line, &result)?;
            let json_value: serde_json::Value = serde_json::from_str(&json_str)?;
            json_objects.push(json_value);
        }

        let json_array = serde_json::Value::Array(json_objects);
        Ok(serde_json::to_string_pretty(&json_array)?)
    }
}

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