#!/usr/bin/perl -w # # Plugin for watching io-bound traffic (in blocks) on disks. # # Usage: Link or copy into /etc/lrrd/client.d/ # # Parameters: # # config (required) # autoconf (optional - used by lrrd-config) # # $Log$ # Revision 1.14 2004/12/10 18:51:44 jimmyo # linux/apt* has been forced to LANG=C, to get predictable output. # # Revision 1.13 2004/12/10 10:47:49 jimmyo # Change name from ${scale} to ${graph_period}, to be more consistent. # # Revision 1.12 2004/12/09 22:12:56 jimmyo # Added "graph_period" option, to make "graph_sums" usable. # # Revision 1.11 2004/11/21 00:17:12 jimmyo # Changed a lot of plugins so they use DERIVE instead of COUNTER. # # Revision 1.10 2004/11/20 23:58:22 jimmyo # The linux/iostat plugin now ignores devices without traffic (Deb#267195). # # Revision 1.9 2004/09/25 22:29:16 jimmyo # Added info fields to a bunch of plugins. # # Revision 1.8 2004/08/24 13:37:29 ilmari # Add total line # # Revision 1.7 2004/05/20 13:57:12 jimmyo # Set categories to some of the plugins. # # Revision 1.6 2004/02/02 18:18:07 jimmyo # Changed to an informative vlabel, since the field.label information has been made shorter. # # Revision 1.5 2004/02/02 17:52:32 jimmyo # Linux/iostat now shows only disks also on machines without devfs. # # Revision 1.4 2004/02/02 16:54:38 jimmyo # Make the iostat plugin work properly. # # Revision 1.3 2004/02/02 16:53:53 jimmyo # Make the iostat plugin work properly. # # Revision 1.2 2004/01/31 19:24:52 jimmyo # Rewrite of linux/iostat by Mike Fedyk (Deb##223373,224113). # # Revision 1.1 2004/01/02 18:50:01 jimmyo # Renamed occurrances of lrrd -> munin # # Revision 1.1.1.1 2004/01/02 15:18:07 jimmyo # Import of LRRD CVS tree after renaming to Munin # # Revision 1.5 2003/12/18 18:09:32 jimmyo # Added total line # # Revision 1.4 2003/12/18 11:01:51 jimmyo # Fix by_dev compare issue. # # Revision 1.3 2003/12/16 17:51:08 jimmyo # Plugin linux/iostat modified. Now runs on 2.6, and now "mirrors" i/o like eth* et al. (Deb#224113, Deb#223373) # # Revision 1.2 2003/11/07 17:43:16 jimmyo # Cleanups and log entries # # # # Magic markers (optional - used by lrrd-config and some installation # scripts): # #%# family=auto #%# capabilities=autoconf use strict; my $detailed_present = my $stat_present = 0; if (system("grep -q '' /proc/diskstats > /dev/null 2>&1") == 0 || system("grep -q 'rio rmerge rsect ruse wio wmerge wsect wuse running use aveq' /proc/partitions > /dev/null 2>&1") == 0) { $detailed_present = 1; } elsif (system("grep -q '^disk_io: [^ ]' /proc/stat") == 0) { $stat_present = 1; } if ( $ARGV[0] and $ARGV[0] eq "autoconf") { if ($detailed_present eq 1 || $stat_present eq 1) { print "yes\n"; exit 0; } print "no\n"; exit 1; } my %devs; if ($detailed_present eq 1) { &fetch_detailed; } # Falling back to /proc/stat elsif ($stat_present eq 1) { &fetch_stat; } if ( $ARGV[0] and $ARGV[0] eq "config") { print "graph_title IOstat\n"; print "graph_args --base 1024 -l 0\n"; print "graph_vlabel blocks per \${graph_period} read (-) / written (+)\n"; print "graph_category disk\n"; print "graph_total Total\n" if (keys (%devs) > 1); print "graph_info This graph shows the I/O to and from block devices.\n"; print "graph_order"; foreach my $key (sort by_dev keys %devs) { print " ", $key, "_read ", $key, "_write "; } print "\n"; foreach my $key (sort by_dev keys %devs) { print $key . "_read.label $devs{$key}->{name}\n"; print $key . "_read.type DERIVE\n"; print $key . "_read.max 900000\n"; print $key . "_read.min 0\n"; print $key . "_read.graph no\n"; print $key . "_write.label $devs{$key}->{name}\n"; print $key . "_write.info I/O on device $devs{$key}->{name}\n"; print $key . "_write.type DERIVE\n"; print $key . "_write.max 900000\n"; print $key . "_write.min 0\n"; print $key . "_write.negative " . $key . "_read\n"; } exit 0; } foreach my $key (sort by_dev keys %devs) { print $key, "_read.value ", $devs{$key}->{rsect}, "\n"; print $key, "_write.value ", $devs{$key}->{wsect}, "\n"; } sub by_dev { return $a cmp $b; } sub fetch_stat() { open (IN, "/proc/stat") or die "Could not open /proc/stat for reading: $!\n"; while () { next unless (/^disk_io:\s*(.+)\s*/); foreach my $dev (split /\s+/) { next unless $dev =~ /\S/; next unless ($dev =~ /\((\d+),(\d+)\):\(\d+,(\d+),(\d+),(\d+),(\d+)\)/); my $name = "dev".$1."_".$2; $devs{$name} = { name => $name, rio => $3, rsect => $4, wio => $5, wsect => $6 }; } } close (IN); } my %maj_count; sub get_disk_count() { my @disk_count; my $major = $_[0]; $maj_count{$major} = 0 unless exists($maj_count{$major}); $disk_count[0] = $maj_count{$major}++; die "Could not find disk_count for major: $major" unless (exists($disk_count[0])); return $disk_count[0]; } sub fetch_detailed() { if (open(DETAILED, "/proc/diskstats") or open(DETAILED, "/proc/partitions")) { while () { if (/^\s+(\d+)\s+\d+\s*\d*\s+([[:alpha:][:digit:]\/]+)\s+(.*)/) { my @fields = split(/\s+/, $3); my $tmpnam = $2; my $major = $1; if ($tmpnam =~ /\d+$/ ) { # Special case for devices like cXdXpX, # like the cciss driver next unless $tmpnam =~ /\/c\d+d\d+$/ } next unless grep { $_ } @fields; $tmpnam =~ s/\/[[:alpha:]]+(\d+)/\/$1/g; $tmpnam =~ s/^([^\/]+)\//$1/; $tmpnam =~ s/\/disc$//; $devs{"dev".$major."_".&get_disk_count($major)} = { major => $major, name => $tmpnam, rio => $fields[0], rmerge => $fields[1], rsect => $fields[2], ruse => $fields[3], wio => $fields[4], wmerge => $fields[5], wsect => $fields[6], wuse => $fields[7], running => $fields[8], use => $fields[9], aveq => $fields[10] }; } } close (DETAILED); } } # vim:syntax=perl