root / plugins / disk / md_iostat_ @ c3660c2a
Historique | Voir | Annoter | Télécharger (7,08 ko)
| 1 |
#!/usr/bin/perl -w |
|---|---|
| 2 |
# |
| 3 |
# Plugin for watching io-bound traffic (in blocks) on disks. |
| 4 |
# |
| 5 |
# Usage: Link or copy into /etc/lrrd/client.d/ |
| 6 |
# |
| 7 |
# Parameters: |
| 8 |
# |
| 9 |
# config (required) |
| 10 |
# autoconf (optional - used by lrrd-config) |
| 11 |
# |
| 12 |
# $Log$ |
| 13 |
# Revision 1.14 2004/12/10 18:51:44 jimmyo |
| 14 |
# linux/apt* has been forced to LANG=C, to get predictable output. |
| 15 |
# |
| 16 |
# Revision 1.13 2004/12/10 10:47:49 jimmyo |
| 17 |
# Change name from ${scale} to ${graph_period}, to be more consistent.
|
| 18 |
# |
| 19 |
# Revision 1.12 2004/12/09 22:12:56 jimmyo |
| 20 |
# Added "graph_period" option, to make "graph_sums" usable. |
| 21 |
# |
| 22 |
# Revision 1.11 2004/11/21 00:17:12 jimmyo |
| 23 |
# Changed a lot of plugins so they use DERIVE instead of COUNTER. |
| 24 |
# |
| 25 |
# Revision 1.10 2004/11/20 23:58:22 jimmyo |
| 26 |
# The linux/iostat plugin now ignores devices without traffic (Deb#267195). |
| 27 |
# |
| 28 |
# Revision 1.9 2004/09/25 22:29:16 jimmyo |
| 29 |
# Added info fields to a bunch of plugins. |
| 30 |
# |
| 31 |
# Revision 1.8 2004/08/24 13:37:29 ilmari |
| 32 |
# Add total line |
| 33 |
# |
| 34 |
# Revision 1.7 2004/05/20 13:57:12 jimmyo |
| 35 |
# Set categories to some of the plugins. |
| 36 |
# |
| 37 |
# Revision 1.6 2004/02/02 18:18:07 jimmyo |
| 38 |
# Changed to an informative vlabel, since the field.label information has been made shorter. |
| 39 |
# |
| 40 |
# Revision 1.5 2004/02/02 17:52:32 jimmyo |
| 41 |
# Linux/iostat now shows only disks also on machines without devfs. |
| 42 |
# |
| 43 |
# Revision 1.4 2004/02/02 16:54:38 jimmyo |
| 44 |
# Make the iostat plugin work properly. |
| 45 |
# |
| 46 |
# Revision 1.3 2004/02/02 16:53:53 jimmyo |
| 47 |
# Make the iostat plugin work properly. |
| 48 |
# |
| 49 |
# Revision 1.2 2004/01/31 19:24:52 jimmyo |
| 50 |
# Rewrite of linux/iostat by Mike Fedyk (Deb##223373,224113). |
| 51 |
# |
| 52 |
# Revision 1.1 2004/01/02 18:50:01 jimmyo |
| 53 |
# Renamed occurrences of lrrd -> munin |
| 54 |
# |
| 55 |
# Revision 1.1.1.1 2004/01/02 15:18:07 jimmyo |
| 56 |
# Import of LRRD CVS tree after renaming to Munin |
| 57 |
# |
| 58 |
# Revision 1.5 2003/12/18 18:09:32 jimmyo |
| 59 |
# Added total line |
| 60 |
# |
| 61 |
# Revision 1.4 2003/12/18 11:01:51 jimmyo |
| 62 |
# Fix by_dev compare issue. |
| 63 |
# |
| 64 |
# Revision 1.3 2003/12/16 17:51:08 jimmyo |
| 65 |
# Plugin linux/iostat modified. Now runs on 2.6, and now "mirrors" i/o like eth* et al. (Deb#224113, Deb#223373) |
| 66 |
# |
| 67 |
# Revision 1.2 2003/11/07 17:43:16 jimmyo |
| 68 |
# Cleanups and log entries |
| 69 |
# |
| 70 |
# |
| 71 |
# |
| 72 |
# Magic markers (optional - used by lrrd-config and some installation |
| 73 |
# scripts): |
| 74 |
# |
| 75 |
#%# family=auto |
| 76 |
#%# capabilities=autoconf |
| 77 |
|
| 78 |
use strict; |
| 79 |
use Data::Dumper; |
| 80 |
|
| 81 |
# Where to get stats from |
| 82 |
my $detailed_present = 0; |
| 83 |
my $stat_present = 0; |
| 84 |
# And md things here? |
| 85 |
my $mdstat_present = 0; |
| 86 |
|
| 87 |
if ( (-f '/proc/diskstats') or |
| 88 |
(system("grep -q 'rio rmerge rsect ruse wio wmerge wsect wuse running use aveq' /proc/partitions") == 0) ) {
|
| 89 |
$detailed_present = 1; |
| 90 |
} elsif (system("grep -q '^disk_io: [^ ]' /proc/stat") == 0) {
|
| 91 |
$stat_present = 1; |
| 92 |
} |
| 93 |
|
| 94 |
$mdstat_present = -f '/proc/mdstat'; |
| 95 |
|
| 96 |
if ( defined($ARGV[0]) and $ARGV[0] eq "autoconf") {
|
| 97 |
if ($mdstat_present and ($detailed_present or $stat_present)) {
|
| 98 |
print "yes\n"; |
| 99 |
exit 0; |
| 100 |
} |
| 101 |
print "no\n"; |
| 102 |
exit 1; |
| 103 |
} |
| 104 |
|
| 105 |
my %devs; |
| 106 |
my %nametodev; |
| 107 |
|
| 108 |
if ($detailed_present) {
|
| 109 |
&fetch_detailed; |
| 110 |
} elsif ($stat_present) {
|
| 111 |
# Falling back to /proc/stat |
| 112 |
&fetch_stat; |
| 113 |
} |
| 114 |
|
| 115 |
my $md = $0; |
| 116 |
$md =~ s/.*_//; |
| 117 |
|
| 118 |
open(MD,"/proc/mdstat"); |
| 119 |
|
| 120 |
my ($dev,$mdstatus,$raid,@devs); |
| 121 |
|
| 122 |
while (<MD>) {
|
| 123 |
next unless /^$md/o; |
| 124 |
($dev, $mdstatus) = split(/\s+:\s+/,$_,2); |
| 125 |
($mdstatus, $raid, @devs) = split(/\s+/,$mdstatus); |
| 126 |
last; |
| 127 |
} |
| 128 |
|
| 129 |
# print "DEVICES: ",join(', ',@devs),"\n";
|
| 130 |
|
| 131 |
# Remove unwanted things like raid device number, partition number |
| 132 |
# and sort nicely. |
| 133 |
@devs = sort by_dev map { s/\d*\[.*\]$//; $_; } @devs;
|
| 134 |
|
| 135 |
# Insert the raid device into the mix. |
| 136 |
unshift(@devs,$md); |
| 137 |
|
| 138 |
# And translate to the device name used by the datastructures. |
| 139 |
@devs = map { $nametodev{$_}; } @devs;
|
| 140 |
|
| 141 |
close(MD); |
| 142 |
my $i=0; |
| 143 |
|
| 144 |
if ( $ARGV[0] and $ARGV[0] eq "config") {
|
| 145 |
print "graph_title IOstat for $md\n"; |
| 146 |
print "graph_args --base 1024 -l 0\n"; |
| 147 |
print "graph_vlabel blocks / \${graph_period} read (-) / written (+)\n";
|
| 148 |
print "graph_category disk\n"; |
| 149 |
print "graph_info This graph shows the I/O to and from block devices comprising the $raid device $md.\n"; |
| 150 |
|
| 151 |
my @grapho = @devs; |
| 152 |
# The first shall be last |
| 153 |
push(@grapho,shift(@grapho)); |
| 154 |
|
| 155 |
print "graph_order"; |
| 156 |
foreach my $key (@grapho) {
|
| 157 |
print " ", $key, "_read ", $key, "_write "; |
| 158 |
} |
| 159 |
print "\n"; |
| 160 |
foreach my $key (@devs) {
|
| 161 |
print $key . "_read.label $devs{$key}->{name}\n";
|
| 162 |
print $key . "_read.type DERIVE\n"; |
| 163 |
print $key . "_read.max 900000\n"; |
| 164 |
print $key . "_read.min 0\n"; |
| 165 |
print $key . "_read.graph no\n"; |
| 166 |
print $key . "_write.label $devs{$key}->{name}\n";
|
| 167 |
print $key . "_write.info I/O on device $devs{$key}->{name}\n";
|
| 168 |
print $key . "_write.type DERIVE\n"; |
| 169 |
print $key . "_write.max 900000\n"; |
| 170 |
print $key . "_write.min 0\n"; |
| 171 |
print $key . "_write.negative " . $key . "_read\n"; |
| 172 |
if ($i == 0) {
|
| 173 |
print "${key}_read.draw LINE2\n";
|
| 174 |
print "${key}_write.draw LINE2\n";
|
| 175 |
} elsif ($i == 1) {
|
| 176 |
print "${key}_read.draw AREA\n";
|
| 177 |
print "${key}_write.draw AREA\n";
|
| 178 |
} else {
|
| 179 |
print "${key}_read.draw STACK\n";
|
| 180 |
print "${key}_write.draw STACK\n";
|
| 181 |
} |
| 182 |
$i++; |
| 183 |
} |
| 184 |
exit 0; |
| 185 |
} |
| 186 |
|
| 187 |
# print Dumper \%nametodev; |
| 188 |
# print Dumper \%devs; |
| 189 |
|
| 190 |
foreach my $key (@devs) {
|
| 191 |
# print "Device name: $key, iostat name: ",$nametodev{$key},"\n";
|
| 192 |
print $key, "_read.value ", $devs{$key}->{rsect}, "\n";
|
| 193 |
print $key, "_write.value ", $devs{$key}->{wsect}, "\n";
|
| 194 |
} |
| 195 |
|
| 196 |
sub by_dev {
|
| 197 |
return $a cmp $b; |
| 198 |
} |
| 199 |
|
| 200 |
sub fetch_stat() {
|
| 201 |
open (IN, "/proc/stat") or die "Could not open /proc/stat for reading: $!\n"; |
| 202 |
|
| 203 |
while (<IN>) {
|
| 204 |
next unless (/^disk_io:\s*(.+)\s*/); |
| 205 |
foreach my $dev (split /\s+/) {
|
| 206 |
next unless $dev =~ /\S/; |
| 207 |
next unless ($dev =~ /\((\d+),(\d+)\):\(\d+,(\d+),(\d+),(\d+),(\d+)\)/); |
| 208 |
|
| 209 |
my $name = "dev".$1."_".$2; |
| 210 |
|
| 211 |
$nametodev{$name}=$name;
|
| 212 |
|
| 213 |
$devs{$name} = {
|
| 214 |
name => $name, |
| 215 |
rio => $3, |
| 216 |
rsect => $4, |
| 217 |
wio => $5, |
| 218 |
wsect => $6 |
| 219 |
}; |
| 220 |
} |
| 221 |
} |
| 222 |
close (IN); |
| 223 |
} |
| 224 |
|
| 225 |
my %maj_count; |
| 226 |
sub get_disk_count() |
| 227 |
{
|
| 228 |
my @disk_count; |
| 229 |
my $major = $_[0]; |
| 230 |
$maj_count{$major} = 0 unless exists($maj_count{$major});
|
| 231 |
$disk_count[0] = $maj_count{$major}++;
|
| 232 |
die "Could not find disk_count for major: $major" unless (exists($disk_count[0])); |
| 233 |
return $disk_count[0]; |
| 234 |
} |
| 235 |
|
| 236 |
|
| 237 |
sub fetch_detailed() {
|
| 238 |
|
| 239 |
if (open(DETAILED, "/proc/diskstats") |
| 240 |
or open(DETAILED, "/proc/partitions")) {
|
| 241 |
while (<DETAILED>) {
|
| 242 |
if (/^\s+(\d+)\s+\d+\s*\d*\s+([[:alpha:][:digit:]\/]+)\s+(.*)/) {
|
| 243 |
my @fields = split(/\s+/, $3); |
| 244 |
my $tmpnam = $2; |
| 245 |
my $major = $1; |
| 246 |
if ($tmpnam =~ /^md\d+/) {
|
| 247 |
# That's fine, we want raid disks reported here. |
| 248 |
} elsif ($tmpnam =~ /\d+$/ ) {
|
| 249 |
# Special case for devices like cXdXpX, |
| 250 |
# like the cciss driver |
| 251 |
next unless $tmpnam =~ /\/c\d+d\d+$/ |
| 252 |
} |
| 253 |
next unless grep { $_ } @fields;
|
| 254 |
|
| 255 |
$tmpnam =~ s/\/[[:alpha:]]+(\d+)/\/$1/g; |
| 256 |
$tmpnam =~ s/^([^\/]+)\//$1/; |
| 257 |
$tmpnam =~ s/\/disc$//; |
| 258 |
|
| 259 |
my $devnam = "dev".$major."_".&get_disk_count($major); |
| 260 |
|
| 261 |
$nametodev{$tmpnam} = $devnam;
|
| 262 |
|
| 263 |
$devs{$devnam} = {
|
| 264 |
major => $major, |
| 265 |
name => $tmpnam, |
| 266 |
rio => $fields[0], |
| 267 |
rmerge => $fields[1], |
| 268 |
rsect => $fields[2], |
| 269 |
ruse => $fields[3], |
| 270 |
wio => $fields[4], |
| 271 |
wmerge => $fields[5], |
| 272 |
wsect => $fields[6], |
| 273 |
wuse => $fields[7], |
| 274 |
running => $fields[8], |
| 275 |
use => $fields[9], |
| 276 |
aveq => $fields[10] |
| 277 |
}; |
| 278 |
} |
| 279 |
} |
| 280 |
close (DETAILED); |
| 281 |
} |
| 282 |
} |
| 283 |
# vim:syntax=perl |
