#!/usr/bin/perl -w
# 
# Plugin to monitor individual interrupts
#
# $Log$
# Revision 1.7.2.1  2005/02/24 17:33:22  jimmyo
# linux/irqstats should no longer fail on some systems (Deb#296452).
#
# Revision 1.7  2004/12/10 18:51:44  jimmyo
# linux/apt* has been forced to LANG=C, to get predictable output.
#
# Revision 1.6  2004/12/10 10:47:49  jimmyo
# Change name from ${scale} to ${graph_period}, to be more consistent.
#
# Revision 1.5  2004/12/09 22:12:56  jimmyo
# Added "graph_period" option, to make "graph_sums" usable.
#
# Revision 1.4  2004/11/20 19:53:04  jimmyo
# Removed debuging-settings. Sorry about that.
#
# Revision 1.3  2004/11/20 18:17:51  jimmyo
# Added i-prefix to value lines as well (forgot earlier).
#
# Revision 1.2  2004/11/19 23:01:40  jimmyo
# Fixed irqstats plugin so it doesn't use numbers as field names. Also expanded the label if possible, since munin-graph now handles long labels.
#
# Revision 1.1  2004/10/26 09:31:04  ilmari
# Added plugin linux/irqstast, showing individual interrupt rates.
#
#
#%# family=auto
#%# capabilities=autoconf
use strict;

if (defined $ARGV[0] && $ARGV[0] eq 'autoconf') {
    if(-r '/proc/interrupts') {
	print "yes\n";
	exit(0);
    } else {
	print "no\n";
	exit(1);
    }
}
open my $in, '<', '/proc/interrupts'
  or die "Can't open /proc/interrupts: $!\n";

my @cpus = split(' ', <$in>);
my $cpus = scalar @cpus;
my $cpu;

if ($0 =~ /(?:.*\/)?irqstats_(.+)/) {
    $cpu = $1;
    if ($cpu > $#cpus) {
	die "Requested CPU $cpu out of bounds (0..$#cpus)\n";
    }
}
my @irqs;


sub sum (@) {
    my $sum = 0;
    $sum += $_ || 0 for @_;	# Avoid complaints about empty strings
    return $sum;
}

while (my $line = <$in>) {
    my ($irq, $label, $type);
    my @data = split(' ', $line, $cpus + 3);
    chomp @data;
    $irq = shift @data;
    next unless length $irq;
    chop $irq;
    if ($irq =~ /^\d+$/) {
	$label = pop @data;
	$type = pop @data;
    }
    # Skip non-per-cpu values for per-cpu stats
    next if defined($cpu) and $cpus > @data;
    push @irqs, {
		 irq => $irq,
		 label => $label,
		 count => defined($cpu) ? $data[$cpu] : sum(@data)
		};
}
close $in;

if (defined $ARGV[0] && $ARGV[0] eq 'config') {
    print 'graph_title Individual interrupts',
      defined($cpu) ? " on CPU $cpu\n" : "\n";
    print <<EOM;
graph_args --base 1000 -l 0;
graph_vlabel interrupts / \${graph_period}
graph_category system
EOM
    print join(' ', 'graph_order', map {"i" . $_->{irq}} @irqs), "\n";
    for my $irq (@irqs) {
	my $f = ($irq->{label} || $irq->{irq});
	$f = $irq->{irq} if (length ($f) > 47);
	print "i", $irq->{irq}, '.label ', $f, "\n";
	print "i", $irq->{irq}, '.info Interrupt ', $irq->{irq}, ', for device(s): ', $irq->{label}, "\n"
	  if $irq->{label};
	print "i", $irq->{irq}, ".type DERIVE\n";
	print "i", $irq->{irq}, ".min 0\n";
    }
} else {
    print "i", $_->{irq}, '.value ', $_->{count}, "\n" for @irqs;
}

