1 |
package Core::Iostat; |
---|
2 |
|
---|
3 |
use strict; |
---|
4 |
use warnings; |
---|
5 |
|
---|
6 |
use base 'Resmon::Module'; |
---|
7 |
|
---|
8 |
use Resmon::ExtComm qw(run_command cache_command); |
---|
9 |
|
---|
10 |
=pod |
---|
11 |
|
---|
12 |
=head1 NAME |
---|
13 |
|
---|
14 |
Core::Iostat - Monitor disk I/O statistics using iostat |
---|
15 |
|
---|
16 |
=head1 SYNOPSIS |
---|
17 |
|
---|
18 |
Core::Iostat { |
---|
19 |
sd0 : noop |
---|
20 |
sd1 : noop |
---|
21 |
} |
---|
22 |
|
---|
23 |
Core::Iostat { |
---|
24 |
hda : iostat_path => /usr/sbin/iostat |
---|
25 |
} |
---|
26 |
|
---|
27 |
=head1 DESCRIPTION |
---|
28 |
|
---|
29 |
This module monitors I/O statistics for a given disk. It uses the running |
---|
30 |
total values reported by iostat. The type and number of metrics returned |
---|
31 |
depend on the type returned by each platform's respective iostat command. |
---|
32 |
|
---|
33 |
=head1 CONFIGURATION |
---|
34 |
|
---|
35 |
=over |
---|
36 |
|
---|
37 |
=item check_name |
---|
38 |
|
---|
39 |
The name of the check refers to the disk to query status for. |
---|
40 |
|
---|
41 |
=item iostat_path |
---|
42 |
|
---|
43 |
Provide an alternate path to the iostat command (optional). |
---|
44 |
|
---|
45 |
=back |
---|
46 |
|
---|
47 |
=head1 METRICS |
---|
48 |
|
---|
49 |
=over |
---|
50 |
|
---|
51 |
=item reads_sec |
---|
52 |
|
---|
53 |
Reads per second. |
---|
54 |
|
---|
55 |
=item writes_sec |
---|
56 |
|
---|
57 |
Writes per second. |
---|
58 |
|
---|
59 |
=item kb_read_sec |
---|
60 |
|
---|
61 |
Kilobytes read per second. |
---|
62 |
|
---|
63 |
=item kb_write_sec |
---|
64 |
|
---|
65 |
Kilobytes written per second. |
---|
66 |
|
---|
67 |
=item lqueue_txn |
---|
68 |
|
---|
69 |
Transaction queue length. |
---|
70 |
|
---|
71 |
=item wait_txn |
---|
72 |
|
---|
73 |
Average number of transactions waiting for service. |
---|
74 |
|
---|
75 |
=item actv_txn |
---|
76 |
|
---|
77 |
Average number of transactions actively being serviced. |
---|
78 |
|
---|
79 |
=item rspt_txn |
---|
80 |
|
---|
81 |
Average response time of transactions, in milliseconds. |
---|
82 |
|
---|
83 |
=item wait_pct |
---|
84 |
|
---|
85 |
Percent of time there are transactions waiting for service. |
---|
86 |
|
---|
87 |
=item busy_pct |
---|
88 |
|
---|
89 |
Percent of time the disk is busy. |
---|
90 |
|
---|
91 |
=item soft_errors |
---|
92 |
|
---|
93 |
Number of soft errors. |
---|
94 |
|
---|
95 |
=item hard_errors |
---|
96 |
|
---|
97 |
Number of hard errors. |
---|
98 |
|
---|
99 |
=item txport_errors |
---|
100 |
|
---|
101 |
Number of transport errors. |
---|
102 |
|
---|
103 |
=item kb_xfrd |
---|
104 |
|
---|
105 |
Kilobytes transferred (counter). |
---|
106 |
|
---|
107 |
=item disk_xfrs |
---|
108 |
|
---|
109 |
Disk transfers (counter). |
---|
110 |
|
---|
111 |
=item busy_sec |
---|
112 |
|
---|
113 |
Seconds spent in disk activity (counter). |
---|
114 |
|
---|
115 |
=item xfrs_sec |
---|
116 |
|
---|
117 |
Disk transfers per second. |
---|
118 |
|
---|
119 |
=back |
---|
120 |
|
---|
121 |
=cut |
---|
122 |
|
---|
123 |
sub handler { |
---|
124 |
my $self = shift; |
---|
125 |
my $disk = $self->{'check_name'}; |
---|
126 |
my $config = $self->{'config'}; |
---|
127 |
my $iostat_path = $config->{'iostat_path'} || 'iostat'; |
---|
128 |
my $osname = $^O; |
---|
129 |
|
---|
130 |
if ($osname eq 'solaris') { |
---|
131 |
my $output = run_command("$iostat_path -xe $disk"); |
---|
132 |
my ($line) = grep(/$disk\s*/, split(/\n/, $output)); |
---|
133 |
if ($line =~ /$disk\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+).*/) { |
---|
134 |
return { |
---|
135 |
'reads_sec' => [$1, 'i'], |
---|
136 |
'writes_sec' => [$2, 'i'], |
---|
137 |
'kb_read_sec' => [$3, 'i'], |
---|
138 |
'kb_write_sec' => [$4, 'i'], |
---|
139 |
'wait_txn' => [$5, 'i'], |
---|
140 |
'actv_txn' => [$6, 'i'], |
---|
141 |
'rspt_txn' => [$7, 'i'], |
---|
142 |
'wait_pct' => [$8, 'i'], |
---|
143 |
'busy_pct' => [$9, 'i'], |
---|
144 |
'soft_errors' => [$10, 'i'], |
---|
145 |
'hard_errors' => [$11, 'i'], |
---|
146 |
'txport_errors' => [$12, 'i'], |
---|
147 |
'total_errors' => [$13, 'i'] |
---|
148 |
}; |
---|
149 |
} else { |
---|
150 |
die "Unable to find disk: $disk\n"; |
---|
151 |
} |
---|
152 |
} elsif ($osname eq 'linux') { |
---|
153 |
my $output = run_command("$iostat_path $disk"); |
---|
154 |
my ($line) = grep(/$disk\s*/, split(/\n/, $output)); |
---|
155 |
if ($line =~ /^$disk\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+).*/) { |
---|
156 |
return { |
---|
157 |
'xfrs_sec' => [$1, 'i'], |
---|
158 |
'reads_sec' => [$2, 'i'], |
---|
159 |
'writes_sec' => [$3, 'i'] |
---|
160 |
}; |
---|
161 |
} else { |
---|
162 |
die "Unable to find disk: $disk\n"; |
---|
163 |
} |
---|
164 |
} elsif ($osname eq 'freebsd') { |
---|
165 |
my $output = run_command("$iostat_path -x $disk"); |
---|
166 |
my ($line) = grep(/$disk\s*/, split(/\n/, $output)); |
---|
167 |
if ($line =~ /^$disk\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\S+).*/) { |
---|
168 |
return { |
---|
169 |
'reads_sec' => [$1, 'i'], |
---|
170 |
'writes_sec' => [$2, 'i'], |
---|
171 |
'kb_read_sec' => [$3, 'i'], |
---|
172 |
'kb_write_sec' => [$4, 'i'], |
---|
173 |
'lqueue_txn' => [$5, 'i'], |
---|
174 |
'rspt_txn' => [$6, 'i'] |
---|
175 |
}; |
---|
176 |
} else { |
---|
177 |
die "Unable to find disk: $disk\n"; |
---|
178 |
} |
---|
179 |
} elsif ($osname eq 'openbsd') { |
---|
180 |
my $output = run_command("$iostat_path -D -I $disk"); |
---|
181 |
if ($output =~ /\s+$disk\s+\n\s+KB xfr time\s+\n\s+(\d+)\s+(\d+)\s+(\S+).*/) { |
---|
182 |
return { |
---|
183 |
'kb_xfrd' => [$1, 'i'], |
---|
184 |
'disk_xfrs' => [$2, 'i'], |
---|
185 |
'busy_sec' => [$3, 'i'] |
---|
186 |
}; |
---|
187 |
} else { |
---|
188 |
die "Unable to find disk: $disk\n"; |
---|
189 |
} |
---|
190 |
} else { |
---|
191 |
die "Unsupported platform: $osname\n"; |
---|
192 |
} |
---|
193 |
}; |
---|
194 |
|
---|
195 |
1; |
---|