2022-05-19 14:02:17 +02:00
class Collector :: Dovecot
class Sieve
def initialize store , prometheus
@store = store
@stored_into_mailbox = prometheus . counter :stored_into_mailbox_total , docstring : 'A counter of mails stored in mailbox by sieve' , labels : % i [ process ]
@forwards = prometheus . counter :forwared_mails_total , docstring : 'A counter of mails forwareded to other address' , labels : % i [ process ]
@discarded_duplicate_forward = prometheus . counter :discarded_duplicate_forward_total , docstring : 'A counter of discarded duplicates, which will not be forwarded.' , labels : % i [ process ]
%w[ lmtp deliver ] . each do | p |
@stored_into_mailbox . increment by : 0 , labels : { process : p }
@forwards . increment by : 0 , labels : { process : p }
@discarded_duplicate_forward . increment by : 0 , labels : { process : p }
end
end
def collect entry , process , msg
case msg
when / stored mail into mailbox /
# dovecot.service dovecot lmtp sieve: lmtp(dillo@nfotex.com)<935639><hhtGGv2ZVmLXRg4AQx2OcA>: sieve: msgid=<1649842684455734173.18148473471766045120@vlmpaymp001.at.inside>: stored mail into mailbox
@stored_into_mailbox . increment labels : { process : process }
when / forwarded to /
@forwards . increment labels : { process : process }
when / discarded duplicate forward to /
@discarded_duplicate_forward . increment labels : { process : process }
else
STDERR . puts " # #{ entry . _systemd_unit } #{ entry . syslog_identifier } sieve| #{ entry . message } "
end
end
end
class Delivery
def initialize store , prometheus , sieve , saved_mailbox , process
@store , @sieve , @process = store , sieve , process
@connect = prometheus . counter " #{ process } _connect_total " , docstring : " A counter of connection via #{ process } "
@disconnect = prometheus . counter " #{ process } _disconnect_total " , docstring : " A counter of disconnect at #{ process } "
@saved_mail_to_mailbox = saved_mailbox
end
def collect entry , msg
case msg
2022-05-23 14:17:11 +02:00
when / \ AConnect from / then @connect . increment
when / \ ADisconnect from / then @disconnect . increment
when / saved mail to / then @saved_mail_to_mailbox . increment labels : { process : @process }
when / \ Asieve: (.*) / then @sieve . collect entry , @process , $1
else STDERR . puts " # #{ entry . _systemd_unit } #{ entry . syslog_identifier } delivery| #{ entry . message } "
2022-05-19 14:02:17 +02:00
end
end
end
class Imap
def initialize store , prometheus
@connection_closed = prometheus . counter :connection_closed_total , docstring : 'A counter of closed connection on dovecot'
@inactivity = prometheus . counter :disconnected_inactivity_total , docstring : 'A counter for disconnect for inactivity.'
@connection_stats = prometheus . counter :connection_stats_total , docstring : 'A counter for observed statistics after disconnected.' , labels : % i [ disconnect_reason ]
@logged_out = prometheus . counter :logged_out_total , docstring : 'A counter of logouts on dovecot'
@maildir_scanning_took_long = prometheus . summary :maildir_scanning_took_long_total , docstring : 'A summary of long taken maildir scanning by reason (why).' , labels : % i [ why ]
@maildir_scanning_took_long_rename = prometheus . counter :maildir_scanning_took_long_renames_total , docstring : 'A counter of rename()-calls while long taken mail dir scanning'
@maildir_scanning_took_long_readdir = prometheus . counter :maildir_scanning_took_long_readdirs_total , docstring : 'A counter of readdir()-calls while long taken mail dir scanning'
disconnect_reasons = [ 'logged out' , 'connection closed' , 'inactivity' ]
disconnect_reasons . each { | r | @connection_stats . increment by : 0 , labels : { disconnect_reason : r } }
@connection_stats =
Hash [ * % i [ in out deleted expunged trashed hdr_count hdr_bytes body_count body_bytes ] . flat_map { | t |
[ t , prometheus . counter ( :" connection_stats_ #{ t } _total " , docstring : " Counter for #{ t } statistics observed after disconnected " ) ]
} ]
end
def collect entry , msg
case msg
when / \ ALogged out (.*) /
# imap(srv_rt0@nfotex.com)<936759><IXxbn4bc4roqAQGQAGoGAWAUP//++Cw+>: Logged out in=38 out=804 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0
@logged_out . increment
$1 . split ( ' ' ) . each { | x | t , v = x . split ( '=' ) ; @connection_stats [ t . to_sym ] & . increment by : v . to_f }
when / \ AConnection closed \ ([^)]+ \ ) (.*) /
# imap(johannes@nfotex.com)<936668><R4OTgIbcCKRQbb9l>: Connection closed (EXAMINE finished 0.041 secs ago) in=5253 out=390971 deleted=0 expunged=0 trashed=0 hdr_count=14 hdr_bytes=6569 body_count=14 body_bytes=336589
@connection_closed . increment
$1 . split ( ' ' ) . each { | x | t , v = x . split ( '=' ) ; @connection_stats [ t . to_sym ] & . increment by : v . to_f }
when / \ AConnection closed: .* failed: \ ([^)]+ \ ) (.*) /
# imap(wiz@nfotex.com)<1447340><0OOGu+XeasMqAoOIC8CCAHA59y+2iMag>: Connection closed: read(size=6100) failed: Connection reset by peer (UID FETCH finished 0.159 secs ago) in=2982 out=17044659 deleted=0 expunged=0 trashed=0 hdr_count=1 hdr_bytes=3724 body_count=169 body_bytes=16970415
@connection_closed . increment
$1 . split ( ' ' ) . each { | x | t , v = x . split ( '=' ) ; @connection_stats [ t . to_sym ] & . increment by : v . to_f }
when / \ ADisconnected for inactivity (.*) /
@inactivity . increment
$1 . split ( ' ' ) . each { | x | t , v = x . split ( '=' ) ; @connection_stats [ t . to_sym ] & . increment by : v . to_f }
when / \ AWarning: Maildir: Scanning .+? took (?<took> \ d+) seconds \ ((?<readdir> \ d+) readdir \ ( \ )s, (?<rename> \ d+) rename \ ( \ )s to cur \/ , why=0x(?<why>[0-9a-fA-F]+) \ ) /
# Warning: Maildir: Scanning /var/mail/nfotex.com/wiz/mails/.Updates/cur took 49 seconds (86044 readdir()s, 0 rename()s to cur/, why=0x80)
m = $~
@maildir_scanning_took_long . observe m [ :took ] . to_i , labels : m [ :why ] . to_i ( 16 )
@maildir_scanning_took_long_rename . increment by : m [ :rename ] . to_i
@maildir_scanning_took_long_readdir . increment by : m [ :readdir ] . to_i
else
STDERR . puts " # #{ entry . _systemd_unit } #{ entry . syslog_identifier } imap| #{ entry . message } "
end
end
end
class ImapLogin
def initialize store , prometheus
@store = store
@logged_in = prometheus . counter :logged_in_total , docstring : 'A counter of successfull logins to dovecot'
@aborted = prometheus . counter :login_aborted_total , docstring : 'A counter of aborted logins'
@disconnected = prometheus . counter :login_disconnected_total , docstring : 'A counter of disconnections before successfully logged in' , labels : % i [ reason ]
end
def collect entry , msg
case msg
when / \ ALogin: user= /
@logged_in . increment
2022-05-23 14:17:11 +02:00
when / \ ADisconnected:? \ ((.*?) \ ): user=< /
2022-05-19 14:02:17 +02:00
case $1
when / \ Ano auth attempts /
@disconnected . increment labels : { reason : 'no auth attempts' }
when / \ Aauth failed /
@disconnected . increment labels : { reason : 'auth failed' }
when / \ AToo many invalid commands /
@disconnected . increment labels : { reason : 'too many invalid commands' }
when / \ AInactivity /
@disconnected . increment labels : { reason : 'inactivity' }
when / \ ADisconnected /
@disconnected . increment labels : { reason : 'disconnected' }
else
@disconnected . increment labels : { reason : '<any>' }
STDERR . puts " # #{ entry . _systemd_unit } #{ entry . syslog_identifier } Disconnected before login| #{ entry . message } "
end
when / \ AAborted login /
@aborted . increment
else
STDERR . puts " # #{ entry . _systemd_unit } #{ entry . syslog_identifier } imap-login| #{ entry . message } "
end
end
end
def initialize store , prometheus
@store = store
2022-10-03 13:54:07 +02:00
@saved_mail_to_mailbox = prometheus . counter :saved_mail_to_mailbox_total , docstring : " A counter of saved mails to mailbox directly " , labels : % i [ process ]
@auth_errors = prometheus . counter :auth_errors_total , docstring : " A counter of dovecot auth errors by type. " , labels : % i [ error ]
2022-05-19 14:02:17 +02:00
@sieve = Sieve . new store , Collector :: PrefixProxy . new ( prometheus , :sieve )
@lmtp = Delivery . new store , prometheus , @sieve , @saved_mail_to_mailbox , :lmtp
@deliver = Delivery . new store , prometheus , @sieve , @saved_mail_to_mailbox , :deliver
@imap_login = ImapLogin . new store , prometheus
@imap = Imap . new store , prometheus
end
def collect entry
# STDERR.puts "dovecot| #{entry.message}"
case entry . message
2022-05-23 14:17:11 +02:00
when / \ Aimap-login: (.*) / then @imap_login . collect entry , $1
when / \ Aimap \ ([^)]+ \ )(?:<[^ ]+>)?: (.*) / then @imap . collect entry , $1
when / \ Almtp \ ([^ ]+ \ )<[^ ]+>: (.*) / then @lmtp . collect entry , $1
when / \ Almtp \ ([^ ]+ \ ): (.*) / then @lmtp . collect entry , $1
when / \ Adeliver(?:[^:]+): (.*) / then @deliver . collect entry , $1
2022-05-19 14:02:17 +02:00
when / \ Aauth: Error: (.*) /
case $1
when / \ ALDAP: Connection lost to LDAP server, /
2022-05-23 14:17:11 +02:00
@auth_errors . increment labels : { error : " ldap connection lost " }
2022-05-19 14:02:17 +02:00
else
STDERR . puts " # #{ entry . _systemd_unit } #{ entry . syslog_identifier } | #{ entry . message } "
2022-05-23 14:17:11 +02:00
@auth_errors . increment labels : { error : " <any> " }
2022-05-19 14:02:17 +02:00
end
2022-05-23 14:17:11 +02:00
else STDERR . puts " # #{ entry . _systemd_unit } #{ entry . syslog_identifier } | #{ entry . message } "
2022-05-19 14:02:17 +02:00
end
end
end