postfix_log_parser/events/
anvil.rs

1//! Anvil连接计数器和统计模块
2//!
3//! 处理Postfix anvil守护进程的事件,包括连接统计、速率限制和配置警告
4
5use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7
8/// Anvil连接计数器事件
9///
10/// 记录Postfix anvil服务的连接统计和配置警告信息
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
12pub struct AnvilEvent {
13    /// 事件发生时间戳(UTC时间)
14    pub timestamp: DateTime<Utc>,
15
16    /// 进程ID(可选)
17    /// anvil进程的系统标识符,某些情况下可能为空
18    pub pid: Option<u32>,
19
20    /// 事件类型(配置警告或统计信息)
21    pub event_type: AnvilEventType,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
25pub enum AnvilEventType {
26    ConfigWarning {
27        file_path: String,
28        line_number: u32,
29        parameter_name: String,
30        message: String,
31    },
32    Statistics {
33        metric_type: StatisticType,
34        value: u32,
35        rate_window: Option<String>, // e.g., "/60s"
36        service_client: String,
37        timestamp: DateTime<Utc>,
38    },
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
42pub enum StatisticType {
43    MaxConnectionRate,
44    MaxConnectionCount,
45    MaxMessageRate,
46    MaxCacheSize,
47}
48
49impl AnvilEvent {
50    pub fn new(timestamp: DateTime<Utc>, pid: Option<u32>, event_type: AnvilEventType) -> Self {
51        Self {
52            timestamp,
53            pid,
54            event_type,
55        }
56    }
57
58    pub fn config_warning(
59        timestamp: DateTime<Utc>,
60        pid: Option<u32>,
61        file_path: String,
62        line_number: u32,
63        parameter_name: String,
64        message: String,
65    ) -> Self {
66        Self::new(
67            timestamp,
68            pid,
69            AnvilEventType::ConfigWarning {
70                file_path,
71                line_number,
72                parameter_name,
73                message,
74            },
75        )
76    }
77
78    pub fn statistics(
79        timestamp: DateTime<Utc>,
80        pid: Option<u32>,
81        metric_type: StatisticType,
82        value: u32,
83        rate_window: Option<String>,
84        service_client: String,
85        metric_timestamp: DateTime<Utc>,
86    ) -> Self {
87        Self::new(
88            timestamp,
89            pid,
90            AnvilEventType::Statistics {
91                metric_type,
92                value,
93                rate_window,
94                service_client,
95                timestamp: metric_timestamp,
96            },
97        )
98    }
99
100    /// Get a human-readable description of the event
101    pub fn description(&self) -> String {
102        match &self.event_type {
103            AnvilEventType::ConfigWarning {
104                file_path,
105                line_number,
106                parameter_name,
107                message,
108            } => {
109                format!(
110                    "Config warning in {}:{} for {}: {}",
111                    file_path, line_number, parameter_name, message
112                )
113            }
114            AnvilEventType::Statistics {
115                metric_type,
116                value,
117                rate_window,
118                service_client,
119                ..
120            } => {
121                let metric_name = match metric_type {
122                    StatisticType::MaxConnectionRate => "connection rate",
123                    StatisticType::MaxConnectionCount => "connection count",
124                    StatisticType::MaxMessageRate => "message rate",
125                    StatisticType::MaxCacheSize => "cache size",
126                };
127
128                if let Some(window) = rate_window {
129                    format!(
130                        "Max {} {}{} for {}",
131                        metric_name, value, window, service_client
132                    )
133                } else {
134                    format!("Max {} {} for {}", metric_name, value, service_client)
135                }
136            }
137        }
138    }
139
140    /// Get event severity for monitoring/alerting
141    pub fn severity(&self) -> &'static str {
142        match &self.event_type {
143            AnvilEventType::ConfigWarning { .. } => "warning",
144            AnvilEventType::Statistics { .. } => "info",
145        }
146    }
147}