postfix_log_parser/formatters/json/
discard.rs

1use serde_json::{json, Map, Value};
2
3use crate::events::discard::{DiscardConfigType, DiscardEvent};
4
5/// DISCARD事件JSON格式化器
6pub struct DiscardJsonFormatter;
7
8impl DiscardJsonFormatter {
9    pub fn new() -> Self {
10        Self
11    }
12
13    pub fn format_event(&self, event: &DiscardEvent) -> Value {
14        let mut base_object = Map::new();
15
16        // 添加组件通用信息
17        base_object.insert("component".to_string(), json!("discard"));
18
19        match event {
20            DiscardEvent::MessageDiscard {
21                base: _base,
22                queue_id,
23                recipient,
24                relay,
25                delay,
26                delays,
27                dsn,
28                status,
29                discard_reason,
30            } => {
31                base_object.insert("event_type".to_string(), json!("message_discard"));
32                base_object.insert("queue_id".to_string(), json!(queue_id));
33                base_object.insert("recipient".to_string(), json!(recipient));
34                base_object.insert("relay".to_string(), json!(relay));
35                base_object.insert("base".to_string(), json!(_base));
36
37                base_object.insert("delay_total_seconds".to_string(), json!(delay));
38
39                // 详细的延迟分析
40                let delay_details = json!({
41                    "queue_wait_seconds": delays.queue_wait,
42                    "connection_setup_seconds": delays.connection_setup,
43                    "connection_time_seconds": delays.connection_time,
44                    "transmission_time_seconds": delays.transmission_time,
45                    "total_seconds": delays.total_delay(),
46                    "is_fast_discard": delays.is_fast_discard(),
47                    "performance_analysis": self.analyze_discard_performance(delays)
48                });
49                base_object.insert("delay_breakdown".to_string(), delay_details);
50
51                base_object.insert("dsn_code".to_string(), json!(dsn));
52                base_object.insert(
53                    "dsn_classification".to_string(),
54                    json!(self.classify_dsn(dsn)),
55                );
56                base_object.insert("delivery_status".to_string(), json!(status));
57                base_object.insert("discard_reason".to_string(), json!(discard_reason));
58
59                // 添加丢弃分析
60                base_object.insert(
61                    "discard_analysis".to_string(),
62                    self.analyze_discard_operation(dsn, status, discard_reason),
63                );
64
65                // 添加邮件流量分析
66                base_object.insert(
67                    "mail_flow_analysis".to_string(),
68                    self.analyze_mail_flow(recipient, discard_reason),
69                );
70
71                // 添加安全性评估
72                base_object.insert(
73                    "security_assessment".to_string(),
74                    self.assess_security_implications(recipient, discard_reason),
75                );
76            }
77
78            DiscardEvent::Configuration {
79                base: _base,
80                config_type,
81                details,
82            } => {
83                base_object.insert("event_type".to_string(), json!("configuration"));
84                base_object.insert("config_type".to_string(), json!(config_type));
85                base_object.insert("config_details".to_string(), json!(details));
86                base_object.insert("base".to_string(), json!(_base));
87
88                // 添加配置分析
89                base_object.insert(
90                    "config_analysis".to_string(),
91                    self.analyze_config_event(config_type, details),
92                );
93            }
94        }
95
96        // 添加组件统计信息
97        base_object.insert(
98            "discard_statistics".to_string(),
99            self.get_discard_statistics(event),
100        );
101
102        Value::Object(base_object)
103    }
104
105    /// 分析丢弃性能
106    fn analyze_discard_performance(
107        &self,
108        delays: &crate::events::discard::DelayBreakdown,
109    ) -> Value {
110        let total = delays.total_delay();
111        let mut analysis = Map::new();
112
113        // 性能评级
114        let performance_rating = if total < 0.01 {
115            "instant"
116        } else if total < 0.05 {
117            "very_fast"
118        } else if total < 0.1 {
119            "fast"
120        } else {
121            "slow"
122        };
123
124        analysis.insert("overall_rating".to_string(), json!(performance_rating));
125
126        // 延迟原因分析
127        let delay_source = if delays.queue_wait > total * 0.8 {
128            "queue_processing"
129        } else if total > 0.1 {
130            "system_load"
131        } else {
132            "normal_processing"
133        };
134
135        analysis.insert("primary_delay_source".to_string(), json!(delay_source));
136
137        // 效率指标
138        analysis.insert(
139            "efficiency_metrics".to_string(),
140            json!({
141                "queue_wait_percentage": if total > 0.0 { (delays.queue_wait / total * 100.0).round() } else { 0.0 },
142                "is_optimal": delays.is_fast_discard(),
143                "expected_range": "0.00-0.05 seconds for optimal performance"
144            }),
145        );
146
147        Value::Object(analysis)
148    }
149
150    /// 分析丢弃操作
151    fn analyze_discard_operation(&self, dsn: &str, status: &str, discard_reason: &str) -> Value {
152        let mut analysis = Map::new();
153
154        // 操作有效性
155        let operation_validity = if status == "sent" && dsn.starts_with("2.") {
156            "successful_discard"
157        } else {
158            "abnormal_discard"
159        };
160
161        analysis.insert("operation_status".to_string(), json!(operation_validity));
162
163        // DSN分析
164        let dsn_class = self.classify_dsn(dsn);
165        analysis.insert("dsn_classification".to_string(), json!(dsn_class));
166
167        // 丢弃原因分析
168        let reason_category = if discard_reason.contains(".") {
169            "domain_based"
170        } else if discard_reason.contains("spam") || discard_reason.contains("reject") {
171            "security_based"
172        } else if discard_reason.contains("policy") {
173            "policy_based"
174        } else {
175            "configuration_based"
176        };
177
178        analysis.insert("discard_category".to_string(), json!(reason_category));
179
180        // 建议操作
181        let recommended_action = match reason_category {
182            "security_based" => "monitor_for_patterns",
183            "policy_based" => "review_policy_rules",
184            "domain_based" => "verify_domain_configuration",
185            _ => "none_required",
186        };
187
188        analysis.insert("recommended_action".to_string(), json!(recommended_action));
189
190        Value::Object(analysis)
191    }
192
193    /// 分析邮件流量
194    fn analyze_mail_flow(&self, recipient: &str, discard_reason: &str) -> Value {
195        let mut analysis = Map::new();
196
197        // 收件人域分析
198        let recipient_domain = recipient.split('@').nth(1).unwrap_or("unknown");
199
200        analysis.insert("recipient_domain".to_string(), json!(recipient_domain));
201
202        // 流量类型判断
203        let traffic_type = if discard_reason == recipient_domain {
204            "domain_redirect"
205        } else if discard_reason.contains("blackhole") {
206            "spam_filtering"
207        } else if discard_reason.contains("test") {
208            "testing_traffic"
209        } else {
210            "policy_discard"
211        };
212
213        analysis.insert("traffic_type".to_string(), json!(traffic_type));
214
215        // 影响评估
216        let impact_level = match traffic_type {
217            "spam_filtering" => "positive",
218            "testing_traffic" => "neutral",
219            "policy_discard" => "informational",
220            _ => "informational",
221        };
222
223        analysis.insert("impact_level".to_string(), json!(impact_level));
224
225        Value::Object(analysis)
226    }
227
228    /// 评估安全性影响
229    fn assess_security_implications(&self, _recipient: &str, discard_reason: &str) -> Value {
230        let mut assessment = Map::new();
231
232        // 安全级别评估
233        let security_level = if discard_reason.contains("spam")
234            || discard_reason.contains("virus")
235            || discard_reason.contains("malware")
236        {
237            "high_security_event"
238        } else if discard_reason.contains("policy") || discard_reason.contains("filter") {
239            "policy_enforcement"
240        } else {
241            "normal_operation"
242        };
243
244        assessment.insert("security_level".to_string(), json!(security_level));
245
246        // 威胁指标
247        let threat_indicators = json!({
248            "potential_spam": discard_reason.contains("spam"),
249            "potential_malware": discard_reason.contains("virus") || discard_reason.contains("malware"),
250            "policy_violation": discard_reason.contains("policy"),
251            "suspicious_domain": discard_reason.contains("suspicious")
252        });
253
254        assessment.insert("threat_indicators".to_string(), threat_indicators);
255
256        // 监控建议
257        let monitoring_recommendation = match security_level {
258            "high_security_event" => "increase_monitoring",
259            "policy_enforcement" => "log_for_compliance",
260            _ => "standard_logging",
261        };
262
263        assessment.insert(
264            "monitoring_recommendation".to_string(),
265            json!(monitoring_recommendation),
266        );
267
268        Value::Object(assessment)
269    }
270
271    /// 分析配置事件
272    fn analyze_config_event(&self, config_type: &DiscardConfigType, details: &str) -> Value {
273        let mut analysis = Map::new();
274
275        // 配置类型分析
276        let config_impact = match config_type {
277            DiscardConfigType::ServiceStartup => "service_lifecycle",
278            DiscardConfigType::TransportMapping => "routing_configuration",
279            DiscardConfigType::DiscardRules => "filtering_rules",
280            DiscardConfigType::Other => "general_configuration",
281        };
282
283        analysis.insert("configuration_impact".to_string(), json!(config_impact));
284
285        // 操作类型
286        let operation_type = if details.contains("starting") {
287            "service_start"
288        } else if details.contains("stopping") {
289            "service_stop"
290        } else if details.contains("warning") {
291            "configuration_warning"
292        } else {
293            "configuration_change"
294        };
295
296        analysis.insert("operation_type".to_string(), json!(operation_type));
297
298        // 重要性级别
299        let importance_level = match config_type {
300            DiscardConfigType::ServiceStartup => "high",
301            DiscardConfigType::DiscardRules => "medium",
302            _ => "low",
303        };
304
305        analysis.insert("importance_level".to_string(), json!(importance_level));
306
307        Value::Object(analysis)
308    }
309
310    /// 分类DSN代码
311    fn classify_dsn(&self, dsn: &str) -> &'static str {
312        match dsn {
313            "2.0.0" => "successful_discard",
314            "2.1.5" => "destination_valid",
315            "2.7.0" => "delivery_successful",
316            _ if dsn.starts_with("2.") => "success_code",
317            _ if dsn.starts_with("4.") => "temporary_failure",
318            _ if dsn.starts_with("5.") => "permanent_failure",
319            _ => "unknown_dsn",
320        }
321    }
322
323    /// 获取丢弃统计信息
324    fn get_discard_statistics(&self, event: &DiscardEvent) -> Value {
325        json!({
326            "event_category": match event {
327                DiscardEvent::MessageDiscard { .. } => "message_discard",
328                DiscardEvent::Configuration { .. } => "configuration"
329            },
330            "processing_status": "completed",
331            "component_health": "operational",
332            "typical_use_cases": [
333                "spam_filtering",
334                "policy_enforcement",
335                "content_filtering",
336                "testing_scenarios"
337            ]
338        })
339    }
340}
341
342impl Default for DiscardJsonFormatter {
343    fn default() -> Self {
344        Self::new()
345    }
346}