mirror of
https://github.com/stalwartlabs/mail-server.git
synced 2025-10-06 10:35:46 +08:00
681 lines
27 KiB
Rust
681 lines
27 KiB
Rust
/*
|
|
* SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd <hello@stalw.art>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
|
*/
|
|
|
|
use std::sync::atomic::Ordering;
|
|
|
|
use atomics::{array::AtomicU32Array, gauge::AtomicGauge, histogram::AtomicHistogram};
|
|
use ipc::{
|
|
collector::{Collector, GlobalInterests, EVENT_TYPES},
|
|
subscriber::Interests,
|
|
};
|
|
|
|
use crate::*;
|
|
|
|
pub(crate) static METRIC_INTERESTS: GlobalInterests = GlobalInterests::new();
|
|
|
|
static EVENT_COUNTERS: AtomicU32Array<TOTAL_EVENT_COUNT> = AtomicU32Array::new();
|
|
static CONNECTION_METRICS: [ConnectionMetrics; TOTAL_CONN_TYPES] = init_conn_metrics();
|
|
|
|
static MESSAGE_INGESTION_TIME: AtomicHistogram<12> =
|
|
AtomicHistogram::<10>::new_short_durations(MetricType::MessageIngestionTime);
|
|
static MESSAGE_INDEX_TIME: AtomicHistogram<12> =
|
|
AtomicHistogram::<10>::new_short_durations(MetricType::MessageFtsIndexTime);
|
|
static MESSAGE_DELIVERY_TIME: AtomicHistogram<12> =
|
|
AtomicHistogram::<18>::new_long_durations(MetricType::DeliveryTotalTime);
|
|
|
|
static MESSAGE_INCOMING_SIZE: AtomicHistogram<12> =
|
|
AtomicHistogram::<12>::new_message_sizes(MetricType::MessageSize);
|
|
static MESSAGE_SUBMISSION_SIZE: AtomicHistogram<12> =
|
|
AtomicHistogram::<12>::new_message_sizes(MetricType::MessageAuthSize);
|
|
static MESSAGE_OUT_REPORT_SIZE: AtomicHistogram<12> =
|
|
AtomicHistogram::<12>::new_message_sizes(MetricType::ReportOutgoingSize);
|
|
|
|
static STORE_DATA_READ_TIME: AtomicHistogram<12> =
|
|
AtomicHistogram::<10>::new_short_durations(MetricType::StoreReadTime);
|
|
static STORE_DATA_WRITE_TIME: AtomicHistogram<12> =
|
|
AtomicHistogram::<10>::new_short_durations(MetricType::StoreWriteTime);
|
|
static STORE_BLOB_READ_TIME: AtomicHistogram<12> =
|
|
AtomicHistogram::<10>::new_short_durations(MetricType::BlobReadTime);
|
|
static STORE_BLOB_WRITE_TIME: AtomicHistogram<12> =
|
|
AtomicHistogram::<10>::new_short_durations(MetricType::BlobWriteTime);
|
|
|
|
static DNS_LOOKUP_TIME: AtomicHistogram<12> =
|
|
AtomicHistogram::<10>::new_short_durations(MetricType::DnsLookupTime);
|
|
|
|
static SERVER_MEMORY: AtomicGauge = AtomicGauge::new(MetricType::ServerMemory);
|
|
static QUEUE_COUNT: AtomicGauge = AtomicGauge::new(MetricType::QueueCount);
|
|
static USER_COUNT: AtomicGauge = AtomicGauge::new(MetricType::UserCount);
|
|
static DOMAIN_COUNT: AtomicGauge = AtomicGauge::new(MetricType::DomainCount);
|
|
|
|
const CONN_SMTP_IN: usize = 0;
|
|
const CONN_SMTP_OUT: usize = 1;
|
|
const CONN_IMAP: usize = 2;
|
|
const CONN_POP3: usize = 3;
|
|
const CONN_HTTP: usize = 4;
|
|
const CONN_SIEVE: usize = 5;
|
|
const TOTAL_CONN_TYPES: usize = 6;
|
|
|
|
pub struct ConnectionMetrics {
|
|
pub active_connections: AtomicGauge,
|
|
pub elapsed: AtomicHistogram<12>,
|
|
}
|
|
|
|
pub struct EventCounter {
|
|
id: EventType,
|
|
value: u32,
|
|
}
|
|
|
|
impl Collector {
|
|
pub fn record_metric(event: EventType, event_id: usize, keys: &[(Key, Value)]) {
|
|
// Increment the event counter
|
|
if !event.is_span_end() && !event.is_raw_io() {
|
|
EVENT_COUNTERS.add(event_id, 1);
|
|
}
|
|
|
|
// Extract variables
|
|
let mut elapsed = 0;
|
|
let mut size = 0;
|
|
for (key, value) in keys {
|
|
match (key, value) {
|
|
(Key::Elapsed, Value::Duration(d)) => elapsed = *d,
|
|
(Key::Size, Value::UInt(s)) => size = *s,
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
match event {
|
|
EventType::Smtp(SmtpEvent::ConnectionStart) => {
|
|
let conn = &CONNECTION_METRICS[CONN_SMTP_IN];
|
|
conn.active_connections.increment();
|
|
}
|
|
EventType::Smtp(SmtpEvent::ConnectionEnd) => {
|
|
let conn = &CONNECTION_METRICS[CONN_SMTP_IN];
|
|
conn.active_connections.decrement();
|
|
conn.elapsed.observe(elapsed);
|
|
}
|
|
EventType::Imap(ImapEvent::ConnectionStart) => {
|
|
let conn = &CONNECTION_METRICS[CONN_IMAP];
|
|
conn.active_connections.increment();
|
|
}
|
|
EventType::Imap(ImapEvent::ConnectionEnd) => {
|
|
let conn = &CONNECTION_METRICS[CONN_IMAP];
|
|
conn.active_connections.decrement();
|
|
conn.elapsed.observe(elapsed);
|
|
}
|
|
EventType::Pop3(Pop3Event::ConnectionStart) => {
|
|
let conn = &CONNECTION_METRICS[CONN_POP3];
|
|
conn.active_connections.increment();
|
|
}
|
|
EventType::Pop3(Pop3Event::ConnectionEnd) => {
|
|
let conn = &CONNECTION_METRICS[CONN_POP3];
|
|
conn.active_connections.decrement();
|
|
conn.elapsed.observe(elapsed);
|
|
}
|
|
EventType::Http(HttpEvent::ConnectionStart) => {
|
|
let conn = &CONNECTION_METRICS[CONN_HTTP];
|
|
conn.active_connections.increment();
|
|
}
|
|
EventType::Http(HttpEvent::ConnectionEnd) => {
|
|
let conn = &CONNECTION_METRICS[CONN_HTTP];
|
|
conn.active_connections.decrement();
|
|
conn.elapsed.observe(elapsed);
|
|
}
|
|
EventType::ManageSieve(ManageSieveEvent::ConnectionStart) => {
|
|
let conn = &CONNECTION_METRICS[CONN_SIEVE];
|
|
conn.active_connections.increment();
|
|
}
|
|
EventType::ManageSieve(ManageSieveEvent::ConnectionEnd) => {
|
|
let conn = &CONNECTION_METRICS[CONN_SIEVE];
|
|
conn.active_connections.decrement();
|
|
conn.elapsed.observe(elapsed);
|
|
}
|
|
EventType::Delivery(DeliveryEvent::AttemptStart) => {
|
|
let conn = &CONNECTION_METRICS[CONN_SMTP_OUT];
|
|
conn.active_connections.increment();
|
|
}
|
|
EventType::Delivery(DeliveryEvent::AttemptEnd) => {
|
|
let conn = &CONNECTION_METRICS[CONN_SMTP_OUT];
|
|
conn.active_connections.decrement();
|
|
conn.elapsed.observe(elapsed);
|
|
}
|
|
EventType::Delivery(DeliveryEvent::Completed) => {
|
|
QUEUE_COUNT.decrement();
|
|
MESSAGE_DELIVERY_TIME.observe(elapsed);
|
|
}
|
|
EventType::Delivery(
|
|
DeliveryEvent::MxLookup | DeliveryEvent::IpLookup | DeliveryEvent::NullMx,
|
|
)
|
|
| EventType::TlsRpt(_)
|
|
| EventType::MtaSts(_)
|
|
| EventType::Dane(_) => {
|
|
if elapsed > 0 {
|
|
DNS_LOOKUP_TIME.observe(elapsed);
|
|
}
|
|
}
|
|
EventType::MessageIngest(
|
|
MessageIngestEvent::Ham
|
|
| MessageIngestEvent::Spam
|
|
| MessageIngestEvent::ImapAppend
|
|
| MessageIngestEvent::JmapAppend,
|
|
) => {
|
|
MESSAGE_INGESTION_TIME.observe(elapsed);
|
|
}
|
|
EventType::Queue(QueueEvent::QueueMessage) => {
|
|
MESSAGE_INCOMING_SIZE.observe(size);
|
|
QUEUE_COUNT.increment();
|
|
}
|
|
EventType::Queue(QueueEvent::QueueMessageAuthenticated) => {
|
|
MESSAGE_SUBMISSION_SIZE.observe(size);
|
|
QUEUE_COUNT.increment();
|
|
}
|
|
EventType::Queue(QueueEvent::QueueReport) => {
|
|
MESSAGE_OUT_REPORT_SIZE.observe(size);
|
|
QUEUE_COUNT.increment();
|
|
}
|
|
EventType::Queue(QueueEvent::QueueAutogenerated | QueueEvent::QueueDsn) => {
|
|
QUEUE_COUNT.increment();
|
|
}
|
|
EventType::FtsIndex(FtsIndexEvent::Index) => {
|
|
MESSAGE_INDEX_TIME.observe(elapsed);
|
|
}
|
|
EventType::Store(StoreEvent::BlobWrite) => {
|
|
STORE_BLOB_WRITE_TIME.observe(elapsed);
|
|
}
|
|
EventType::Store(StoreEvent::BlobRead) => {
|
|
STORE_BLOB_READ_TIME.observe(elapsed);
|
|
}
|
|
EventType::Store(StoreEvent::DataWrite) => {
|
|
STORE_DATA_WRITE_TIME.observe(elapsed);
|
|
}
|
|
EventType::Store(StoreEvent::DataIterate) => {
|
|
STORE_DATA_READ_TIME.observe(elapsed);
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn is_metric(event: impl Into<usize>) -> bool {
|
|
METRIC_INTERESTS.get(event)
|
|
}
|
|
|
|
pub fn set_metrics(interests: Interests) {
|
|
METRIC_INTERESTS.update(interests);
|
|
}
|
|
|
|
pub fn collect_counters(_is_enterprise: bool) -> impl Iterator<Item = EventCounter> {
|
|
EVENT_COUNTERS
|
|
.inner()
|
|
.iter()
|
|
.enumerate()
|
|
.filter_map(|(event_id, value)| {
|
|
let value = value.load(Ordering::Relaxed);
|
|
if value > 0 {
|
|
Some(EventCounter {
|
|
id: EVENT_TYPES[event_id],
|
|
value,
|
|
})
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
}
|
|
|
|
pub fn collect_gauges(is_enterprise: bool) -> impl Iterator<Item = &'static AtomicGauge> {
|
|
static E_GAUGES: &[&AtomicGauge] =
|
|
&[&SERVER_MEMORY, &QUEUE_COUNT, &USER_COUNT, &DOMAIN_COUNT];
|
|
static C_GAUGES: &[&AtomicGauge] = &[&SERVER_MEMORY, &USER_COUNT, &DOMAIN_COUNT];
|
|
|
|
if is_enterprise { E_GAUGES } else { C_GAUGES }
|
|
.iter()
|
|
.copied()
|
|
.chain(CONNECTION_METRICS.iter().map(|m| &m.active_connections))
|
|
}
|
|
|
|
pub fn collect_histograms(
|
|
is_enterprise: bool,
|
|
) -> impl Iterator<Item = &'static AtomicHistogram<12>> {
|
|
static E_HISTOGRAMS: &[&AtomicHistogram<12>] = &[
|
|
&MESSAGE_INGESTION_TIME,
|
|
&MESSAGE_INDEX_TIME,
|
|
&MESSAGE_DELIVERY_TIME,
|
|
&MESSAGE_INCOMING_SIZE,
|
|
&MESSAGE_SUBMISSION_SIZE,
|
|
&MESSAGE_OUT_REPORT_SIZE,
|
|
&STORE_DATA_READ_TIME,
|
|
&STORE_DATA_WRITE_TIME,
|
|
&STORE_BLOB_READ_TIME,
|
|
&STORE_BLOB_WRITE_TIME,
|
|
&DNS_LOOKUP_TIME,
|
|
];
|
|
static C_HISTOGRAMS: &[&AtomicHistogram<12>] = &[
|
|
&MESSAGE_DELIVERY_TIME,
|
|
&MESSAGE_INCOMING_SIZE,
|
|
&MESSAGE_SUBMISSION_SIZE,
|
|
];
|
|
|
|
if is_enterprise {
|
|
E_HISTOGRAMS
|
|
} else {
|
|
C_HISTOGRAMS
|
|
}
|
|
.iter()
|
|
.copied()
|
|
.chain(CONNECTION_METRICS.iter().map(|m| &m.elapsed))
|
|
.filter(|h| h.is_active())
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn read_event_metric(metric_id: usize) -> u32 {
|
|
EVENT_COUNTERS.get(metric_id)
|
|
}
|
|
|
|
pub fn read_metric(metric_type: MetricType) -> f64 {
|
|
match metric_type {
|
|
MetricType::ServerMemory => SERVER_MEMORY.get() as f64,
|
|
MetricType::MessageIngestionTime => MESSAGE_INGESTION_TIME.average(),
|
|
MetricType::MessageFtsIndexTime => MESSAGE_INDEX_TIME.average(),
|
|
MetricType::MessageSize => MESSAGE_INCOMING_SIZE.average(),
|
|
MetricType::MessageAuthSize => MESSAGE_SUBMISSION_SIZE.average(),
|
|
MetricType::DeliveryTotalTime => MESSAGE_DELIVERY_TIME.average(),
|
|
MetricType::DeliveryTime => CONNECTION_METRICS[CONN_SMTP_OUT].elapsed.average(),
|
|
MetricType::DeliveryActiveConnections => {
|
|
CONNECTION_METRICS[CONN_SMTP_OUT].active_connections.get() as f64
|
|
}
|
|
MetricType::QueueCount => QUEUE_COUNT.get() as f64,
|
|
MetricType::ReportOutgoingSize => MESSAGE_OUT_REPORT_SIZE.average(),
|
|
MetricType::StoreReadTime => STORE_DATA_READ_TIME.average(),
|
|
MetricType::StoreWriteTime => STORE_DATA_WRITE_TIME.average(),
|
|
MetricType::BlobReadTime => STORE_BLOB_READ_TIME.average(),
|
|
MetricType::BlobWriteTime => STORE_BLOB_WRITE_TIME.average(),
|
|
MetricType::DnsLookupTime => DNS_LOOKUP_TIME.average(),
|
|
MetricType::HttpActiveConnections => {
|
|
CONNECTION_METRICS[CONN_HTTP].active_connections.get() as f64
|
|
}
|
|
MetricType::HttpRequestTime => CONNECTION_METRICS[CONN_HTTP].elapsed.average(),
|
|
MetricType::ImapActiveConnections => {
|
|
CONNECTION_METRICS[CONN_IMAP].active_connections.get() as f64
|
|
}
|
|
MetricType::ImapRequestTime => CONNECTION_METRICS[CONN_IMAP].elapsed.average(),
|
|
MetricType::Pop3ActiveConnections => {
|
|
CONNECTION_METRICS[CONN_POP3].active_connections.get() as f64
|
|
}
|
|
MetricType::Pop3RequestTime => CONNECTION_METRICS[CONN_POP3].elapsed.average(),
|
|
MetricType::SmtpActiveConnections => {
|
|
CONNECTION_METRICS[CONN_SMTP_IN].active_connections.get() as f64
|
|
}
|
|
MetricType::SmtpRequestTime => CONNECTION_METRICS[CONN_SMTP_IN].elapsed.average(),
|
|
MetricType::SieveActiveConnections => {
|
|
CONNECTION_METRICS[CONN_SIEVE].active_connections.get() as f64
|
|
}
|
|
MetricType::SieveRequestTime => CONNECTION_METRICS[CONN_SIEVE].elapsed.average(),
|
|
MetricType::UserCount => USER_COUNT.get() as f64,
|
|
MetricType::DomainCount => DOMAIN_COUNT.get() as f64,
|
|
}
|
|
}
|
|
|
|
pub fn update_gauge(metric_type: MetricType, value: u64) {
|
|
match metric_type {
|
|
MetricType::ServerMemory => SERVER_MEMORY.set(value),
|
|
MetricType::QueueCount => QUEUE_COUNT.set(value),
|
|
MetricType::UserCount => USER_COUNT.set(value),
|
|
MetricType::DomainCount => DOMAIN_COUNT.set(value),
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
pub fn update_event_counter(event_type: EventType, value: u32) {
|
|
EVENT_COUNTERS.add(event_type.into(), value);
|
|
}
|
|
|
|
pub fn update_histogram(metric_type: MetricType, value: u64) {
|
|
match metric_type {
|
|
MetricType::MessageIngestionTime => MESSAGE_INGESTION_TIME.observe(value),
|
|
MetricType::MessageFtsIndexTime => MESSAGE_INDEX_TIME.observe(value),
|
|
MetricType::DeliveryTotalTime => MESSAGE_DELIVERY_TIME.observe(value),
|
|
MetricType::DeliveryTime => CONNECTION_METRICS[CONN_SMTP_OUT].elapsed.observe(value),
|
|
MetricType::DnsLookupTime => DNS_LOOKUP_TIME.observe(value),
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl EventCounter {
|
|
pub fn id(&self) -> EventType {
|
|
self.id
|
|
}
|
|
|
|
pub fn value(&self) -> u64 {
|
|
self.value as u64
|
|
}
|
|
}
|
|
|
|
impl ConnectionMetrics {
|
|
#[allow(clippy::new_without_default)]
|
|
pub const fn new() -> Self {
|
|
Self {
|
|
active_connections: AtomicGauge::new(MetricType::BlobReadTime),
|
|
elapsed: AtomicHistogram::<18>::new_medium_durations(MetricType::BlobReadTime),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::declare_interior_mutable_const)]
|
|
const fn init_conn_metrics() -> [ConnectionMetrics; TOTAL_CONN_TYPES] {
|
|
const INIT: ConnectionMetrics = ConnectionMetrics::new();
|
|
let mut array = [INIT; TOTAL_CONN_TYPES];
|
|
let mut i = 0;
|
|
while i < TOTAL_CONN_TYPES {
|
|
let metric = match i {
|
|
CONN_HTTP => &[
|
|
MetricType::HttpRequestTime,
|
|
MetricType::HttpActiveConnections,
|
|
],
|
|
CONN_IMAP => &[
|
|
MetricType::ImapRequestTime,
|
|
MetricType::ImapActiveConnections,
|
|
],
|
|
CONN_POP3 => &[
|
|
MetricType::Pop3RequestTime,
|
|
MetricType::Pop3ActiveConnections,
|
|
],
|
|
CONN_SMTP_IN => &[
|
|
MetricType::SmtpRequestTime,
|
|
MetricType::SmtpActiveConnections,
|
|
],
|
|
CONN_SMTP_OUT => &[
|
|
MetricType::DeliveryTime,
|
|
MetricType::DeliveryActiveConnections,
|
|
],
|
|
CONN_SIEVE => &[
|
|
MetricType::SieveRequestTime,
|
|
MetricType::SieveActiveConnections,
|
|
],
|
|
_ => &[MetricType::BlobReadTime, MetricType::BlobReadTime],
|
|
};
|
|
|
|
array[i] = ConnectionMetrics {
|
|
elapsed: AtomicHistogram::<18>::new_medium_durations(metric[0]),
|
|
active_connections: AtomicGauge::new(metric[1]),
|
|
};
|
|
i += 1;
|
|
}
|
|
array
|
|
}
|
|
|
|
impl EventType {
|
|
pub fn is_metric(&self) -> bool {
|
|
match self {
|
|
EventType::Server(ServerEvent::ThreadError) => true,
|
|
EventType::Purge(PurgeEvent::Error) => true,
|
|
EventType::Eval(
|
|
EvalEvent::Error | EvalEvent::StoreNotFound | EvalEvent::DirectoryNotFound,
|
|
) => true,
|
|
EventType::Acme(
|
|
AcmeEvent::TlsAlpnError
|
|
| AcmeEvent::OrderCompleted
|
|
| AcmeEvent::AuthError
|
|
| AcmeEvent::AuthTooManyAttempts
|
|
| AcmeEvent::DnsRecordCreationFailed
|
|
| AcmeEvent::DnsRecordDeletionFailed
|
|
| AcmeEvent::DnsRecordPropagationTimeout
|
|
| AcmeEvent::ClientMissingSni
|
|
| AcmeEvent::TokenNotFound
|
|
| AcmeEvent::DnsRecordLookupFailed
|
|
| AcmeEvent::OrderInvalid
|
|
| AcmeEvent::Error,
|
|
) => true,
|
|
EventType::Store(
|
|
StoreEvent::AssertValueFailed
|
|
| StoreEvent::FoundationdbError
|
|
| StoreEvent::MysqlError
|
|
| StoreEvent::PostgresqlError
|
|
| StoreEvent::RocksdbError
|
|
| StoreEvent::SqliteError
|
|
| StoreEvent::LdapError
|
|
| StoreEvent::ElasticsearchError
|
|
| StoreEvent::RedisError
|
|
| StoreEvent::S3Error
|
|
| StoreEvent::FilesystemError
|
|
| StoreEvent::PoolError
|
|
| StoreEvent::DataCorruption
|
|
| StoreEvent::DecompressError
|
|
| StoreEvent::DeserializeError
|
|
| StoreEvent::NotFound
|
|
| StoreEvent::NotConfigured
|
|
| StoreEvent::NotSupported
|
|
| StoreEvent::UnexpectedError
|
|
| StoreEvent::CryptoError
|
|
| StoreEvent::BlobMissingMarker
|
|
| StoreEvent::DataWrite
|
|
| StoreEvent::DataIterate
|
|
| StoreEvent::BlobRead
|
|
| StoreEvent::BlobWrite
|
|
| StoreEvent::BlobDelete,
|
|
) => true,
|
|
EventType::MessageIngest(_) => true,
|
|
EventType::Jmap(
|
|
JmapEvent::MethodCall
|
|
| JmapEvent::WebsocketStart
|
|
| JmapEvent::WebsocketError
|
|
| JmapEvent::UnsupportedFilter
|
|
| JmapEvent::UnsupportedSort
|
|
| JmapEvent::Forbidden
|
|
| JmapEvent::NotJson
|
|
| JmapEvent::NotRequest
|
|
| JmapEvent::InvalidArguments
|
|
| JmapEvent::RequestTooLarge
|
|
| JmapEvent::UnknownMethod,
|
|
) => true,
|
|
EventType::Imap(ImapEvent::ConnectionStart | ImapEvent::ConnectionEnd) => true,
|
|
EventType::ManageSieve(
|
|
ManageSieveEvent::ConnectionStart | ManageSieveEvent::ConnectionEnd,
|
|
) => true,
|
|
EventType::Pop3(Pop3Event::ConnectionStart | Pop3Event::ConnectionEnd) => true,
|
|
EventType::Smtp(
|
|
SmtpEvent::ConnectionStart
|
|
| SmtpEvent::ConnectionEnd
|
|
| SmtpEvent::Error
|
|
| SmtpEvent::ConcurrencyLimitExceeded
|
|
| SmtpEvent::TransferLimitExceeded
|
|
| SmtpEvent::RateLimitExceeded
|
|
| SmtpEvent::TimeLimitExceeded
|
|
| SmtpEvent::MessageParseFailed
|
|
| SmtpEvent::MessageTooLarge
|
|
| SmtpEvent::LoopDetected
|
|
| SmtpEvent::DkimPass
|
|
| SmtpEvent::DkimFail
|
|
| SmtpEvent::ArcPass
|
|
| SmtpEvent::ArcFail
|
|
| SmtpEvent::SpfEhloPass
|
|
| SmtpEvent::SpfEhloFail
|
|
| SmtpEvent::SpfFromPass
|
|
| SmtpEvent::SpfFromFail
|
|
| SmtpEvent::DmarcPass
|
|
| SmtpEvent::DmarcFail
|
|
| SmtpEvent::IprevPass
|
|
| SmtpEvent::IprevFail
|
|
| SmtpEvent::TooManyMessages
|
|
| SmtpEvent::InvalidEhlo
|
|
| SmtpEvent::DidNotSayEhlo
|
|
| SmtpEvent::MailFromUnauthenticated
|
|
| SmtpEvent::MailFromUnauthorized
|
|
| SmtpEvent::MailFromMissing
|
|
| SmtpEvent::MultipleMailFrom
|
|
| SmtpEvent::MailboxDoesNotExist
|
|
| SmtpEvent::RelayNotAllowed
|
|
| SmtpEvent::RcptToDuplicate
|
|
| SmtpEvent::RcptToMissing
|
|
| SmtpEvent::TooManyRecipients
|
|
| SmtpEvent::TooManyInvalidRcpt
|
|
| SmtpEvent::AuthMechanismNotSupported
|
|
| SmtpEvent::AuthExchangeTooLong
|
|
| SmtpEvent::CommandNotImplemented
|
|
| SmtpEvent::InvalidCommand
|
|
| SmtpEvent::SyntaxError
|
|
| SmtpEvent::RequestTooLarge,
|
|
) => true,
|
|
EventType::Http(
|
|
HttpEvent::Error
|
|
| HttpEvent::RequestBody
|
|
| HttpEvent::ResponseBody
|
|
| HttpEvent::XForwardedMissing,
|
|
) => true,
|
|
EventType::Network(NetworkEvent::Timeout) => true,
|
|
EventType::Security(_) => true,
|
|
EventType::Limit(_) => true,
|
|
EventType::Manage(_) => false,
|
|
EventType::Auth(
|
|
AuthEvent::Success
|
|
| AuthEvent::Failed
|
|
| AuthEvent::TooManyAttempts
|
|
| AuthEvent::Error,
|
|
) => true,
|
|
EventType::Config(_) => false,
|
|
EventType::Resource(
|
|
ResourceEvent::NotFound | ResourceEvent::BadParameters | ResourceEvent::Error,
|
|
) => true,
|
|
EventType::Arc(
|
|
ArcEvent::ChainTooLong
|
|
| ArcEvent::InvalidInstance
|
|
| ArcEvent::InvalidCv
|
|
| ArcEvent::HasHeaderTag
|
|
| ArcEvent::BrokenChain,
|
|
) => true,
|
|
EventType::Dkim(_) => true,
|
|
EventType::Dmarc(_) => true,
|
|
EventType::Iprev(_) => true,
|
|
EventType::Dane(
|
|
DaneEvent::AuthenticationSuccess
|
|
| DaneEvent::AuthenticationFailure
|
|
| DaneEvent::NoCertificatesFound
|
|
| DaneEvent::CertificateParseError
|
|
| DaneEvent::TlsaRecordFetchError
|
|
| DaneEvent::TlsaRecordNotFound
|
|
| DaneEvent::TlsaRecordNotDnssecSigned
|
|
| DaneEvent::TlsaRecordInvalid,
|
|
) => true,
|
|
EventType::Spf(_) => true,
|
|
EventType::MailAuth(_) => true,
|
|
EventType::Tls(TlsEvent::HandshakeError) => true,
|
|
EventType::Sieve(
|
|
SieveEvent::ActionAccept
|
|
| SieveEvent::ActionAcceptReplace
|
|
| SieveEvent::ActionDiscard
|
|
| SieveEvent::ActionReject
|
|
| SieveEvent::SendMessage
|
|
| SieveEvent::MessageTooLarge
|
|
| SieveEvent::RuntimeError
|
|
| SieveEvent::UnexpectedError
|
|
| SieveEvent::NotSupported
|
|
| SieveEvent::QuotaExceeded,
|
|
) => true,
|
|
EventType::Spam(
|
|
SpamEvent::PyzorError
|
|
| SpamEvent::ListUpdated
|
|
| SpamEvent::Train
|
|
| SpamEvent::TrainError
|
|
| SpamEvent::Classify
|
|
| SpamEvent::ClassifyError
|
|
| SpamEvent::NotEnoughTrainingData,
|
|
) => true,
|
|
EventType::PushSubscription(_) => true,
|
|
EventType::Cluster(
|
|
ClusterEvent::PeerOffline
|
|
| ClusterEvent::PeerSuspected
|
|
| ClusterEvent::PeerSuspectedIsAlive
|
|
| ClusterEvent::EmptyPacket
|
|
| ClusterEvent::InvalidPacket
|
|
| ClusterEvent::DecryptionError
|
|
| ClusterEvent::Error,
|
|
) => true,
|
|
EventType::Housekeeper(_) => false,
|
|
EventType::FtsIndex(
|
|
FtsIndexEvent::Index
|
|
| FtsIndexEvent::BlobNotFound
|
|
| FtsIndexEvent::MetadataNotFound,
|
|
) => true,
|
|
EventType::Milter(
|
|
MilterEvent::ActionAccept
|
|
| MilterEvent::ActionDiscard
|
|
| MilterEvent::ActionReject
|
|
| MilterEvent::ActionTempFail
|
|
| MilterEvent::ActionReplyCode
|
|
| MilterEvent::ActionConnectionFailure
|
|
| MilterEvent::ActionShutdown,
|
|
) => true,
|
|
EventType::MtaHook(_) => true,
|
|
EventType::Delivery(
|
|
DeliveryEvent::AttemptStart
|
|
| DeliveryEvent::AttemptEnd
|
|
| DeliveryEvent::MxLookupFailed
|
|
| DeliveryEvent::IpLookupFailed
|
|
| DeliveryEvent::NullMx
|
|
| DeliveryEvent::GreetingFailed
|
|
| DeliveryEvent::EhloRejected
|
|
| DeliveryEvent::AuthFailed
|
|
| DeliveryEvent::MailFromRejected
|
|
| DeliveryEvent::Delivered
|
|
| DeliveryEvent::RcptToRejected
|
|
| DeliveryEvent::RcptToFailed
|
|
| DeliveryEvent::MessageRejected
|
|
| DeliveryEvent::StartTlsUnavailable
|
|
| DeliveryEvent::StartTlsError
|
|
| DeliveryEvent::StartTlsDisabled
|
|
| DeliveryEvent::ImplicitTlsError
|
|
| DeliveryEvent::ConcurrencyLimitExceeded
|
|
| DeliveryEvent::RateLimitExceeded
|
|
| DeliveryEvent::DoubleBounce
|
|
| DeliveryEvent::DsnSuccess
|
|
| DeliveryEvent::DsnTempFail
|
|
| DeliveryEvent::DsnPermFail,
|
|
) => true,
|
|
EventType::Queue(
|
|
QueueEvent::QueueMessage
|
|
| QueueEvent::QueueMessageAuthenticated
|
|
| QueueEvent::QueueReport
|
|
| QueueEvent::QueueDsn
|
|
| QueueEvent::QueueAutogenerated
|
|
| QueueEvent::Rescheduled
|
|
| QueueEvent::BlobNotFound
|
|
| QueueEvent::RateLimitExceeded
|
|
| QueueEvent::ConcurrencyLimitExceeded
|
|
| QueueEvent::QuotaExceeded,
|
|
) => true,
|
|
EventType::TlsRpt(_) => false,
|
|
EventType::MtaSts(
|
|
MtaStsEvent::Authorized | MtaStsEvent::NotAuthorized | MtaStsEvent::InvalidPolicy,
|
|
) => true,
|
|
EventType::IncomingReport(_) => true,
|
|
EventType::OutgoingReport(
|
|
OutgoingReportEvent::SpfReport
|
|
| OutgoingReportEvent::SpfRateLimited
|
|
| OutgoingReportEvent::DkimReport
|
|
| OutgoingReportEvent::DkimRateLimited
|
|
| OutgoingReportEvent::DmarcReport
|
|
| OutgoingReportEvent::DmarcRateLimited
|
|
| OutgoingReportEvent::DmarcAggregateReport
|
|
| OutgoingReportEvent::TlsAggregate
|
|
| OutgoingReportEvent::HttpSubmission
|
|
| OutgoingReportEvent::UnauthorizedReportingAddress
|
|
| OutgoingReportEvent::ReportingAddressValidationError
|
|
| OutgoingReportEvent::NotFound
|
|
| OutgoingReportEvent::SubmissionError
|
|
| OutgoingReportEvent::NoRecipientsFound,
|
|
) => true,
|
|
EventType::Telemetry(
|
|
TelemetryEvent::LogError
|
|
| TelemetryEvent::WebhookError
|
|
| TelemetryEvent::OtelExporterError
|
|
| TelemetryEvent::OtelMetricsExporterError
|
|
| TelemetryEvent::PrometheusExporterError
|
|
| TelemetryEvent::JournalError,
|
|
) => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|