The following shows the default configuration.
[postfix*]
- env.logdir /var/log
- env.logfile syslog
+ env.logdir /var/log
+ env.logfile syslog
=head1 INTERPRETATION
# 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 || 0);
-
- while (my $line = <$LOGFILE>) {
- chomp ($line);
-
- if ($line =~ /qmgr.*: ([0-9A-Za-z]+): 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-Za-z]+): 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(@volumes_per_queue_id{@expired_queue_ids});
- return tail_close($LOGFILE);
+ my ($start) = @_;
+
+ open(my $LOGFILE, '-|', "journalctl --facility=mail --after-cursor='$start' --show-cursor");
+
+ while (my $line = <$LOGFILE>) {
+ chomp $line;
+
+ if ($line =~ /qmgr.*: ([0-9A-Za-z]+): 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-Za-z]+): 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;
+ }
+ } elsif ($line =~ /^-- cursor: (.+)$/) {
+ $start = $1;
+ }
+ }
+ close($LOGFILE);
+ # 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(@volumes_per_queue_id{@expired_queue_ids});
+ return $start;
}
if ( $ARGV[0] and $ARGV[0] eq "autoconf" ) {
- my $logfile;
- `which postconf >/dev/null 2>/dev/null`;
- if (!$?) {
- $logfile = "$LOGDIR/$LOGFILE";
-
- if (-f $logfile) {
- if (-r "$logfile") {
- print "yes\n";
- exit 0;
- } else {
- print "no (logfile '$logfile' not readable)\n";
- }
- } else {
- print "no (logfile '$logfile' not found)\n";
- }
- } else {
- print "no (postfix not found)\n";
- }
-
- exit 0;
+ my $logfile;
+ `which postconf >/dev/null 2>/dev/null`;
+ if (!$?) { # if postconf returns success
+ `journalctl --facility=mail --show-cursor -n 0`;
+ if (!$?) { # if journalctl returns success
+ print "yes\n";
+ } else {
+ print "no (journalctl returned error)\n";
+ }
+ } else {
+ print "no (postfix not found)\n";
+ }
+
+ exit 0;
}
if ( $ARGV[0] and $ARGV[0] eq "config" ) {
- print "graph_title Postfix bytes throughput\n";
- print "graph_args --base 1000 -l 0\n";
- print "graph_vlabel bytes / \${graph_period}\n";
- print "graph_scale yes\n";
- print "graph_category postfix\n";
- print "volume.label delivered volume\n";
- print "volume.type DERIVE\n";
- print "volume.min 0\n";
- exit 0;
+ print "graph_title Postfix bytes throughput\n";
+ print "graph_args --base 1000 -l 0\n";
+ print "graph_vlabel bytes / \${graph_period}\n";
+ print "graph_scale yes\n";
+ print "graph_category postfix\n";
+ print "volume.label delivered volume\n";
+ print "volume.type DERIVE\n";
+ print "volume.min 0\n";
+ exit 0;
}
-my $logfile = "$LOGDIR/$LOGFILE";
-
-if (! -f $logfile) {
- print "volume.value U\n";
- exit 0;
-}
-
# load the stored data
($pos, $volume_delivered, $serialized_volumes_queue) = restore_state();
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.
+ # 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
+ my $cursor = `journalctl --facility=mail --show-cursor -n 0 | tail -n 1`;
+ $pos = ($cursor =~ s/^-- cursor: //r);
- $volume_delivered = 0;
- %volumes_per_queue_id = ();
+ $volume_delivered = 0;
+ %volumes_per_queue_id = ();
} else {
- # decode the serialized hash
- # source format: "$id1=$size1:$timestamp1 $id2=$size2:$timestamp2 ..."
- # The "serialized" value may be undefined, in case we just upgraded from the version before
- # 2018, since that old version stored only two fields in the state file. Tolerate this.
- for my $queue_item_descriptor (split(/ /, $serialized_volumes_queue || "")) {
- (my $queue_item_id, my $queue_item_content) = split(/=/, $queue_item_descriptor);
- (my $size, my $timestamp) = split(/:/, $queue_item_content);
- $volumes_per_queue_id{$queue_item_id} = { size => int($size), timestamp => int($timestamp) };
- }
- $pos = parseLogfile ($logfile, $pos);
+ # decode the serialized hash
+ # source format: "$id1=$size1:$timestamp1 $id2=$size2:$timestamp2 ..."
+ # The "serialized" value may be undefined, in case we just upgraded from the version before
+ # 2018, since that old version stored only two fields in the state file. Tolerate this.
+ for my $queue_item_descriptor (split(/ /, $serialized_volumes_queue || "")) {
+ (my $queue_item_id, my $queue_item_content) = split(/=/, $queue_item_descriptor);
+ (my $size, my $timestamp) = split(/:/, $queue_item_content);
+ $volumes_per_queue_id{$queue_item_id} = { size => int($size), timestamp => int($timestamp) };
+ }
+ $pos = parseLogfile($pos);
}
print "volume.value $volume_delivered\n";