postfix-log-parser 0.2.0

高性能模块化Postfix日志解析器,经3.2GB生产数据验证,SMTPD事件100%准确率
Documentation
use crate::events::PostfixLogEvent;
use thiserror::Error;

/// 解析错误类型
#[derive(Error, Debug, Clone)]
pub enum ParseError {
    #[error("无法识别的组件: {component}")]
    UnknownComponent { component: String },

    #[error("无效的时间戳格式: {timestamp}")]
    InvalidTimestamp { timestamp: String },

    #[error("无效的日志格式: {reason}")]
    InvalidLogFormat { reason: String },

    #[error("组件解析失败: {component} - {reason}")]
    ComponentParseError { component: String, reason: String },

    #[error("正则表达式错误: {0}")]
    RegexError(#[from] regex::Error),

    #[error("日期时间解析错误: {0}")]
    ChronoParseError(#[from] chrono::ParseError),
}

/// 解析结果
///
/// 包含解析得到的事件、置信度和可能的错误信息
#[derive(Debug, Clone)]
pub struct ParseResult {
    /// 解析得到的事件,如果解析失败则为 None
    pub event: Option<PostfixLogEvent>,

    /// 解析置信度 (0.0 - 1.0)
    /// - 1.0: 完全匹配
    /// - 0.7-0.9: 模糊匹配
    /// - 0.3-0.6: 部分解析
    /// - 0.0-0.2: 解析失败
    pub confidence: f32,

    /// 解析过程中的错误和警告信息
    pub parsing_errors: Vec<String>,
}

impl ParseResult {
    /// 创建成功的解析结果
    pub fn success(event: PostfixLogEvent, confidence: f32) -> Self {
        Self {
            event: Some(event),
            confidence,
            parsing_errors: Vec::new(),
        }
    }

    /// 创建失败的解析结果
    pub fn failure(error: ParseError) -> Self {
        Self {
            event: None,
            confidence: 0.0,
            parsing_errors: vec![error.to_string()],
        }
    }

    /// 创建部分成功的解析结果
    pub fn partial(event: PostfixLogEvent, confidence: f32, warnings: Vec<String>) -> Self {
        Self {
            event: Some(event),
            confidence,
            parsing_errors: warnings,
        }
    }

    /// 检查解析是否成功
    pub fn is_success(&self) -> bool {
        self.event.is_some() && self.confidence > 0.5
    }

    /// 检查解析是否完全失败
    pub fn is_failure(&self) -> bool {
        self.event.is_none()
    }

    /// 获取主要错误(如果有的话)
    pub fn main_error(&self) -> Option<&String> {
        self.parsing_errors.first()
    }
}