#!@@PERL@@ -w
#
# Plugin to monitor number of pages pr printer printed by CUPS
#
# Usage: copy or link into /etc/munin/plugins
#
# Parameters:
#
#       config   (required)
#       autoconf (optional - used by munin-config)
#
# Config variables:
#
#       logdir       - Which logfile to use
#       logfile      - What file to read in logdir
#       maxlabel     - Maximum printers to plot
#
# Magic markers (optinal - used by munin-config and some installation
# scripts):
#
#%# family=auto
#%# capabilities=autoconf

use strict;

my $statefile = "@@PLUGSTATE@@/munin-cupsys-pages.state";
my $pos       = undef;
my %printers  = ();

my $LOGDIR    = $ENV{logdir}   || "/var/log/cups/";
my $LOGFILE   = $ENV{logfile}  || "page_log";
my $MAXLABEL  = $ENV{maxlabel} || 20;

if($ARGV[0] and $ARGV[0] eq "autoconf" ) {
    my $logfile;
    if(-d $LOGDIR) {
	$logfile = "$LOGDIR/$LOGFILE";
	if(-f $logfile) {
	    if(-r $logfile) {
		print "yes\n";
		exit 0;
	    } else {
		print "no (logfile not readable)\n";
	    }
	} else {
	    print "no (logfile not found)\n";
	}
    } else {
	print "no (could not find logdir)\n";
    }
    exit 1;
}

my $logfile = "$LOGDIR/$LOGFILE";
my $rotlogfile = $logfile . ".0";
if (-f "$logfile.0") {
    $rotlogfile = $logfile . ".0";
} elsif (-f "$logfile.1") {
    $rotlogfile = $logfile . ".1";
} elsif (-f "$logfile.01") {
    $rotlogfile = $logfile . ".01";
} 

if (! -f $logfile and ! -f $rotlogfile) {
    print "pages.value $logfile $rotlogfile U\n";
    exit 0;
}

if (-f "$statefile") {
    open(IN, "$statefile") or exit 4;
    if(<IN> =~ /^(\d+)$/) {
	$pos = $1;
    }
    LINE: while(<IN>) {
	if(/^([^:]+):(\d+)$/) {
	    $printers{$1} = $2;
	}
	if(keys(%printers) >= $MAXLABEL) {
	    last LINE;
	}
    }
    close(IN);
}

my $startsize = (stat $logfile)[7];

if (!defined $pos) {
    # Initial run.
    $pos = $startsize;
    $pos = 0;
}
if ($startsize < $pos) {
    # Log rotated
    parselogfile ($rotlogfile, $pos, (stat $rotlogfile)[7]);
    $pos = 0;
}

parselogfile($logfile, $pos, $startsize);
$pos = $startsize;

# Write back to state file
open (STATFILE, ">$statefile") or exit 4;
print STATFILE "$pos\n";
foreach my $printer (sort(keys %printers)) {
    print STATFILE "$printer:".$printers{$printer}."\n";
}
close(STATFILE);

if($ARGV[0] and $ARGV[0] eq "config") {
    print "host_name $ENV{FQDN}\n";
    print "graph_title CUPS pages printed\n";
    print "graph_args --base 1000 -l 0\n";
    print "graph_vlabel pages/\${graph_period}\n";
    print "graph_order ".join(" ",sort(keys(%printers)))."\n";
    foreach my $printer (sort(keys %printers)) {
	print "$printer.label $printer\n";
	print "$printer.type DERIVE\n";
	print "$printer.min 0\n";
    }
    exit 0;
} else {
    foreach my $printer (sort(keys %printers)) {
	print "$printer.value ".$printers{$printer}."\n";
    }
}

sub parselogfile {    
    my ($fname, $start, $stop) = @_;
    open (LOGFILE, $fname) or exit 3;
    seek (LOGFILE, $start, 0) or exit 2;
    while (tell(LOGFILE) < $stop) {
	my $line = <LOGFILE>;
	chomp ($line);
	if ($line =~ /^(\S+)\s+\S+\s+\d+\s+\[[^\]]+\]\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)$/) {
	    if(!defined($printers{$1}) && keys(%printers) < $MAXLABEL) {
		$printers{$1} += int($2)*int($3);
	    } elsif(defined($printers{$1})) {
		$printers{$1} += int($2)*int($3);
	    }
	} 
    }
    close(LOGFILE);    
}
