postfix_log_parser/events/
base.rs1use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7
8use super::{
9 anvil::AnvilEvent, bounce::BounceEvent, discard::DiscardEvent, master::MasterEvent,
10 pickup::PickupEvent, postfix_script::PostfixScriptEvent, postmap::PostmapEvent,
11 postsuper::PostsuperEvent, relay::RelayEvent, trivial_rewrite::TrivialRewriteEvent,
12 CleanupEvent, ErrorEvent, LocalEvent, QmgrEvent, SmtpEvent, SmtpdEvent, VirtualEvent,
13};
14
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
18pub struct BaseEvent {
19 pub timestamp: DateTime<Utc>,
22
23 pub hostname: String,
26
27 pub component: String,
30
31 pub process_id: u32,
34
35 pub log_level: PostfixLogLevel,
38
39 pub raw_message: String,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct PostfixLogEvent {
49 pub raw_log: String,
53
54 pub timestamp: DateTime<Utc>,
58
59 pub hostname: String,
63
64 pub component: String,
68
69 pub process_id: u32,
73
74 pub log_level: PostfixLogLevel,
78
79 pub event: ComponentEvent,
83
84 pub queue_id: Option<String>,
88}
89
90impl PostfixLogEvent {
91 #[allow(clippy::too_many_arguments)]
93 pub fn new(
94 raw_log: String,
95 timestamp: DateTime<Utc>,
96 hostname: String,
97 component: String,
98 process_id: u32,
99 log_level: PostfixLogLevel,
100 event: ComponentEvent,
101 queue_id: Option<String>,
102 ) -> Self {
103 Self {
104 raw_log,
105 timestamp,
106 hostname,
107 component,
108 process_id,
109 log_level,
110 event,
111 queue_id,
112 }
113 }
114
115 pub fn event_type(&self) -> &'static str {
117 self.event.event_type()
118 }
119
120 pub fn is_error_level(&self) -> bool {
122 self.log_level.is_error_level()
123 }
124
125 pub fn is_warning_level(&self) -> bool {
127 self.log_level.is_warning_level()
128 }
129
130 pub fn is_debug_level(&self) -> bool {
132 self.log_level.is_debug_level()
133 }
134
135 pub fn severity_level(&self) -> u8 {
137 self.log_level.severity_level()
138 }
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
145pub enum ComponentEvent {
146 Smtpd(SmtpdEvent),
148 Qmgr(QmgrEvent),
150 Smtp(SmtpEvent),
152 Cleanup(CleanupEvent),
154 Error(ErrorEvent),
156 Relay(RelayEvent),
158 Discard(DiscardEvent),
160 Bounce(BounceEvent),
162 PostfixScript(PostfixScriptEvent),
164 Master(MasterEvent),
166 Local(LocalEvent),
168 Pickup(PickupEvent),
170 Postmap(PostmapEvent),
172 Postsuper(PostsuperEvent),
174 Anvil(AnvilEvent),
176 TrivialRewrite(TrivialRewriteEvent),
178 Virtual(VirtualEvent),
180 Postlogd(crate::events::postlogd::PostlogdEvent),
182 Proxymap(crate::events::proxymap::ProxymapEvent),
184 Sendmail(crate::events::sendmail::SendmailEvent),
185 Unknown(UnknownEvent),
187}
188
189impl ComponentEvent {
190 pub fn event_type(&self) -> &'static str {
192 match self {
193 ComponentEvent::Smtpd(event) => event.event_type(),
194 ComponentEvent::Qmgr(event) => event.event_type(),
195 ComponentEvent::Smtp(event) => event.event_type(),
196 ComponentEvent::Cleanup(event) => event.event_type(),
197 ComponentEvent::Error(event) => event.event_type(),
198 ComponentEvent::Relay(_) => "relay",
199 ComponentEvent::Discard(_) => "discard",
200 ComponentEvent::Bounce(event) => event.event_type(),
201 ComponentEvent::PostfixScript(_) => "postfix-script",
202 ComponentEvent::Master(event) => event.event_type(),
203 ComponentEvent::Local(event) => event.event_type(),
204 ComponentEvent::Pickup(_) => "pickup",
205 ComponentEvent::Postmap(_) => "postmap",
206 ComponentEvent::Postsuper(_) => "postsuper",
207 ComponentEvent::Anvil(_) => "anvil",
208 ComponentEvent::TrivialRewrite(_) => "trivial-rewrite",
209 ComponentEvent::Virtual(event) => event.event_type(),
210 ComponentEvent::Postlogd(_) => "postlogd",
211 ComponentEvent::Proxymap(_) => "proxymap",
212 ComponentEvent::Sendmail(_) => "sendmail",
213 ComponentEvent::Unknown(_) => "unknown",
214 }
215 }
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct UnknownEvent {
222 pub component: String,
224 pub message: String,
226}
227
228#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
231pub enum PostfixLogLevel {
232 Debug,
234 Info,
236 Warning,
238 Error,
240 Fatal,
242 Panic,
244}
245
246impl PostfixLogLevel {
247 pub fn severity_level(&self) -> u8 {
249 match self {
250 PostfixLogLevel::Debug => 1,
251 PostfixLogLevel::Info => 2,
252 PostfixLogLevel::Warning => 3,
253 PostfixLogLevel::Error => 4,
254 PostfixLogLevel::Fatal => 5,
255 PostfixLogLevel::Panic => 6,
256 }
257 }
258
259 pub fn is_error_level(&self) -> bool {
261 matches!(
262 self,
263 PostfixLogLevel::Error | PostfixLogLevel::Fatal | PostfixLogLevel::Panic
264 )
265 }
266
267 pub fn is_warning_level(&self) -> bool {
269 matches!(self, PostfixLogLevel::Warning)
270 }
271
272 pub fn is_debug_level(&self) -> bool {
274 matches!(self, PostfixLogLevel::Debug)
275 }
276
277 pub fn as_str(&self) -> &'static str {
279 match self {
280 PostfixLogLevel::Debug => "debug",
281 PostfixLogLevel::Info => "info",
282 PostfixLogLevel::Warning => "warning",
283 PostfixLogLevel::Error => "error",
284 PostfixLogLevel::Fatal => "fatal",
285 PostfixLogLevel::Panic => "panic",
286 }
287 }
288
289 pub fn from_prefix(prefix: &str) -> Option<Self> {
291 match prefix.to_lowercase().as_str() {
292 "debug:" => Some(PostfixLogLevel::Debug),
293 "warning:" => Some(PostfixLogLevel::Warning),
294 "error:" => Some(PostfixLogLevel::Error),
295 "fatal:" => Some(PostfixLogLevel::Fatal),
296 "panic:" => Some(PostfixLogLevel::Panic),
297 _ => None,
298 }
299 }
300}
301
302impl Default for PostfixLogLevel {
303 fn default() -> Self {
305 PostfixLogLevel::Info
306 }
307}
308
309impl std::fmt::Display for PostfixLogLevel {
310 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
311 write!(f, "{}", self.as_str())
312 }
313}