Skip to content

Commit

Permalink
Plugin postfix_mailvolume: calculate separate volume for delivered mails
Browse files Browse the repository at this point in the history
  • Loading branch information
sumpfralle authored and neonwork committed Feb 25, 2019
1 parent 36e3754 commit bd1a967
Showing 1 changed file with 49 additions and 17 deletions.
66 changes: 49 additions & 17 deletions plugins/node.d/postfix_mailvolume.in
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ None known
=head1 VERSION
$Id$
v1.1 2018-03-24
* calculate extra field for mail volume that is actually delivered ("volume_delivered")
=head1 AUTHOR
Expand All @@ -49,27 +50,56 @@ GPLv2
=cut

use strict;
use warnings;
use Munin::Plugin;

my $pos = undef;
my $volume = 0;
my $pos = undef;
# the volume that was actually delivered
my $volume_delivered = 0;
my %volumes_per_queue_id = ();
my %expired_queue_ids = ();
# Discard old queue IDs after a while (otherwise the state storage grows infinitely). We need to
# store the IDs long enough for the gap between two delivery attempts. Thus multiple hours are
# recommended.
use constant queue_id_expiry => 6 * 3600;

my $LOGDIR = $ENV{'logdir'} || '/var/log';
my $LOGFILE = $ENV{'logfile'} || 'syslog';


sub parseLogfile {
my ($fname, $start) = @_;

my ($LOGFILE,$rotated) = tail_open($fname,$start);
my ($LOGFILE, $rotated) = tail_open($fname, $start || 0);

my $line;
while (my $line = <$LOGFILE>) {
chomp ($line);

while ($line =<$LOGFILE>) {
chomp ($line);

if ($line =~ /qmgr.*from=.*size=([0-9]+)/) {
$volume += $1;
}
if ($line =~ /qmgr.*: ([0-9A-F]+): from=.*, size=([0-9]+)/) {
# The line with queue ID and size may pass along multiple times (every time the mail
# is moved into the active queue for another delivery attempt). The size should always
# be the same.
if (not exists($volumes_per_queue_id{$1})) {
$volumes_per_queue_id{$1} = {timestamp => time};
}
# probably it is the same value as before
$volumes_per_queue_id{$1}{size} = $2;
} elsif ($line =~ / ([0-9A-F]+): to=.*, status=sent /) {
# The "sent" line is repeated for every successful delivery for each recipient.
if (exists($volumes_per_queue_id{$1})) {
$volume_delivered += $volumes_per_queue_id{$1}{size};
$volumes_per_queue_id{$1}{timestamp} = time;
}
}
}
# remove all expired queue IDs
my @expired_queue_ids;
for my $key (keys %volumes_per_queue_id) {
if (time > $volumes_per_queue_id{$key}{timestamp} + queue_id_expiry) {
push @expired_queue_ids, $key;
}
}
delete(@expired_queue_ids{@expired_queue_ids});
return tail_close($LOGFILE);
}

Expand Down Expand Up @@ -103,7 +133,7 @@ if ( $ARGV[0] and $ARGV[0] eq "config" ) {
print "graph_vlabel bytes / \${graph_period}\n";
print "graph_scale yes\n";
print "graph_category postfix\n";
print "volume.label throughput\n";
print "volume.label delivered volume\n";
print "volume.type DERIVE\n";
print "volume.min 0\n";
exit 0;
Expand All @@ -117,23 +147,25 @@ if (! -f $logfile) {
exit 1;
}

($pos,$volume) = restore_state();
($pos, $volume_delivered, %volumes_per_queue_id) = restore_state();


if (!defined($volume)) {
if (!defined($volume_delivered)) {

# No state file present. Avoid startup spike: Do not read log
# file up to now, but remember how large it is now, and next
# time read from there.

$pos = (stat $logfile)[7]; # File size

$volume = 0;
$volume_delivered = 0;
%volumes_per_queue_id = ();
} else {
$pos = parseLogfile ($logfile, $pos);
}

print "volume.value $volume\n";
print "volume.value $volume_delivered\n";

save_state($pos,$volume);
save_state($pos, $volume_delivered, %volumes_per_queue_id);

# vim:syntax=perl

0 comments on commit bd1a967

Please sign in to comment.