diff --git a/plugins/other/md_iostat_ b/plugins/other/md_iostat_ new file mode 100755 index 00000000..9382bca4 --- /dev/null +++ b/plugins/other/md_iostat_ @@ -0,0 +1,283 @@ +#!/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; +use Data::Dumper; + +# Where to get stats from +my $detailed_present = 0; +my $stat_present = 0; +# And md things here? +my $mdstat_present = 0; + +if ( (-f '/proc/diskstats') or + (system("grep -q 'rio rmerge rsect ruse wio wmerge wsect wuse running use aveq' /proc/partitions") == 0) ) { + $detailed_present = 1; +} elsif (system("grep -q '^disk_io: [^ ]' /proc/stat") == 0) { + $stat_present = 1; +} + +$mdstat_present = -f '/proc/mdstat'; + +if ( defined($ARGV[0]) and $ARGV[0] eq "autoconf") { + if ($mdstat_present and ($detailed_present or $stat_present)) { + print "yes\n"; + exit 0; + } + print "no\n"; + exit 1; +} + +my %devs; +my %nametodev; + +if ($detailed_present) { + &fetch_detailed; +} elsif ($stat_present) { + # Falling back to /proc/stat + &fetch_stat; +} + +my $md = $0; +$md =~ s/.*_//; + +open(MD,"/proc/mdstat"); + +my ($dev,$mdstatus,$raid,@devs); + +while () { + next unless /^$md/o; + ($dev, $mdstatus) = split(/\s+:\s+/,$_,2); + ($mdstatus, $raid, @devs) = split(/\s+/,$mdstatus); + last; +} + +# print "DEVICES: ",join(', ',@devs),"\n"; + +# Remove unwanted things like raid device number, partition number +# and sort nicely. +@devs = sort by_dev map { s/\d*\[.*\]$//; $_; } @devs; + +# Insert the raid device into the mix. +unshift(@devs,$md); + +# And translate to the device name used by the datastructures. +@devs = map { $nametodev{$_}; } @devs; + +close(MD); +my $i=0; + +if ( $ARGV[0] and $ARGV[0] eq "config") { + print "graph_title IOstat for $md\n"; + print "graph_args --base 1024 -l 0\n"; + print "graph_vlabel blocks / \${graph_period} read (-) / written (+)\n"; + print "graph_category disk\n"; + print "graph_info This graph shows the I/O to and from block devices comprising the $raid device $md.\n"; + + my @grapho = @devs; + # The first shall be last + push(@grapho,shift(@grapho)); + + print "graph_order"; + foreach my $key (@grapho) { + print " ", $key, "_read ", $key, "_write "; + } + print "\n"; + foreach my $key (@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"; + if ($i == 0) { + print "${key}_read.draw LINE2\n"; + print "${key}_write.draw LINE2\n"; + } elsif ($i == 1) { + print "${key}_read.draw AREA\n"; + print "${key}_write.draw AREA\n"; + } else { + print "${key}_read.draw STACK\n"; + print "${key}_write.draw STACK\n"; + } + $i++; + } + exit 0; +} + +# print Dumper \%nametodev; +# print Dumper \%devs; + +foreach my $key (@devs) { + # print "Device name: $key, iostat name: ",$nametodev{$key},"\n"; + 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; + + $nametodev{$name}=$name; + + $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 =~ /^md\d+/) { + # That's fine, we want raid disks reported here. + } elsif ($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$//; + + my $devnam = "dev".$major."_".&get_disk_count($major); + + $nametodev{$tmpnam} = $devnam; + + $devs{$devnam} = { + 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