Annotation of nagios/check_rrd/bin/check_rrd, Revision 1.3
1.1 andrew 1: #!/usr/bin/perl -T
1.3 ! andrew 2: # $RedRiver: check_rrd,v 1.2 2006/11/07 20:23:03 andrew Exp $
1.1 andrew 3: ########################################################################
4: # check_rrd *** A nagios check for changing averages in rrds
5: #
6: # 2006.05.01 #*#*# andrew fresh <andrew@mad-techies.org>
7: ########################################################################
1.3 ! andrew 8: # Want to make this do 3 checks
! 9: # * check percentage difference on day, hour, 5 min
! 10: # * check actual number high/low
! 11: # * check last time
! 12: ########################################################################
1.1 andrew 13: use strict;
14: use warnings;
15: use RRDs;
16:
1.3 ! andrew 17: use Data::Dumper;
! 18:
1.1 andrew 19: %ENV = ();
20:
21: use POSIX;
22: use lib "/usr/local/libexec/nagios";
23: use utils qw($TIMEOUT %ERRORS &print_revision &support);
24:
25: use Getopt::Long;
26: Getopt::Long::Configure('bundling');
27:
28: my $PROGNAME = "check_rrd";
29:
30: my %TIMES = (
31: FIVE_MINUTES => 5 * 60,
32: ONE_HOUR => 1 * 60 * 60,
33: ONE_DAY => 1 * 24 * 60 * 60,
34: );
35:
1.3 ! andrew 36: my %Checks = (
! 37: max => {
! 38: #warn => undef,
! 39: #crit => undef,
! 40: warn => -60,
! 41: crit => -50,
! 42: },
! 43: min => {
! 44: #warn => undef,
! 45: #crit => undef,
! 46: warn => -80,
! 47: crit => -85,
! 48: },
! 49: change => {
! 50: warn => 5,
! 51: crit => 10,
! 52: },
! 53: time => {
! 54: warn => 15 * 60, # 15 minutes
! 55: crit => 60 * 60, # 1 hour
! 56: },
! 57: );
! 58:
1.1 andrew 59: my $state = 'UNKNOWN'; # tells whether the it is warning, critical, or OK
60: my %states; # This stores the count of states;
61: my $filename;
62: my @rras;
63: my $warning;
64: my $critical;
65: my $opt_V;
66:
67: #Option checking
68: my $status = GetOptions(
69: "version|V" => \$opt_V,
70: "filename|f=s" => \$filename,
1.2 andrew 71: "rra|r=s" => \@rras,
1.1 andrew 72: "warning|w=s" => \$warning,
73: "critical|c=s" => \$critical,
74: );
75: @rras = split(/,/,join(',',@rras));
76:
77: if ($status == 0) {
78: print_help() ;
79: exit $ERRORS{'OK'};
80: }
81:
82: if ($opt_V) {
1.3 ! andrew 83: print_revision($PROGNAME,'$Revision: 1.2 $ ');
1.1 andrew 84: exit $ERRORS{'OK'};
85: }
86:
87: unless (defined $filename) {
88: print_help();
89: exit $ERRORS{'OK'};
90: }
91:
1.3 ! andrew 92: my $info = RRDs::info($filename) or die "Problem with info from '$filename': $!";
1.1 andrew 93:
94: my $resolution = $info->{'step'};
95: my $last = $info->{'last_update'};
96:
1.3 ! andrew 97: my $age = time - $last;
! 98: if ($age > $Checks{'time'}{'crit'}) {
! 99: push @{ $states{'CRITICAL'} },
! 100: "Last check was too long ago";
! 101: } elsif ($age > $Checks{'time'}{'warn'}) {
! 102: push @{ $states{'WARNING'} },
! 103: "Last check was too long ago";
! 104: } else {
! 105: push @{ $states{'OK'} },
! 106: "Last check was within time limits";
! 107: }
! 108:
1.1 andrew 109: my $end = int($last / $resolution) * $resolution;
110: my $start = int( ($end - $TIMES{'ONE_DAY'}) / $resolution) * $resolution;
111:
112: my ($first, $step, $names, $data) = RRDs::fetch(
1.2 andrew 113: $filename,
1.1 andrew 114: 'AVERAGE',
115: '-r', $resolution,
116: '-s', $start,
117: '-e', $end
1.3 ! andrew 118: ) or die "Problem fetching from '$filename': $!";
1.1 andrew 119:
120: my %totals;
121: foreach my $line (@$data) {
122: foreach my $i (0 .. $#{ $line }) {
123: next unless defined $line->[$i];
124: foreach my $key (keys %TIMES) {
125: if ($end - $TIMES{$key} < $start) {
126: foreach ('max', 'min') {
127: $totals{ $names->[$i] }{$key}{$_} = $line->[$i]
128: unless defined $totals{ $names->[$i] }{$key}{$_};
129: }
130: no warnings q/uninitialized/;
131: $totals{ $names->[$i] }{$key}{'count'}++;
132: $totals{ $names->[$i] }{$key}{'total'} += $line->[$i];
133: $totals{ $names->[$i] }{$key}{'max'} = $line->[$i]
134: if $totals{ $names->[$i] }{$key}{'max'} < $line->[$i];
135: $totals{ $names->[$i] }{$key}{'min'} = $line->[$i]
136: if $totals{ $names->[$i] }{$key}{'min'} > $line->[$i];
137: }
138: }
139: }
140: $start += $step;
141: }
142:
143:
144: foreach my $key (keys %totals) {
145: foreach my $length (keys %{ $totals{$key} }) {
146: $totals{$key}{$length}{'average'} =
147: $totals{$key}{$length}{'total'} /
148: $totals{$key}{$length}{'count'}
149: if $totals{$key}{$length}{'count'};
150: }
151: }
152:
153: foreach my $key (keys %totals) {
1.3 ! andrew 154: next if @rras and not grep { /^$key$/ } @rras;
! 155:
! 156: my $mins = $totals{$key}{'FIVE_MINUTES'}{'average'};
! 157: my $hour = $totals{$key}{'ONE_HOUR'}{'average'};
! 158: my $day = $totals{$key}{'ONE_DAY'}{'average'};
! 159:
! 160:
! 161: my ($s, $m) = check_delta($day, $hour);
! 162: push @{ $states{$s} }, "$key: Hour $m";
! 163:
! 164: ($s, $m) = check_delta($hour, $mins);
! 165: push @{ $states{$s} }, "$key: Minute $m";
! 166:
! 167: ($s, $m) = check_max($day);
! 168: push @{ $states{$s} }, "$key: Day $m";
! 169:
! 170: ($s, $m) = check_min($day);
! 171: push @{ $states{$s} }, "$key: Day $m";
! 172:
! 173: ($s, $m) = check_max($hour);
! 174: push @{ $states{$s} }, "$key: Hour $m";
! 175:
! 176: ($s, $m) = check_min($hour);
! 177: push @{ $states{$s} }, "$key: Hour $m";
! 178:
! 179: ($s, $m) = check_max($mins);
! 180: push @{ $states{$s} }, "$key: Minute $m";
! 181:
! 182: ($s, $m) = check_min($mins);
! 183: push @{ $states{$s} }, "$key: Minute $m";
! 184:
1.1 andrew 185: print $key, ": ";
186: print join ", ",
1.3 ! andrew 187: $totals{$key}{'ONE_DAY'}{'average'},
1.1 andrew 188: $totals{$key}{'ONE_HOUR'}{'average'},
1.3 ! andrew 189: $totals{$key}{'FIVE_MINUTES'}{'average'};
1.1 andrew 190: print "\n";
191: }
192:
1.3 ! andrew 193: print Dumper \%states;
! 194:
1.1 andrew 195: exit $ERRORS{$state};
196:
197:
198: sub print_help {
199: print <<EOL;
200: $PROGNAME plugin for Nagios checks averages in rrds
201: $PROGNAME -f <FILENAME> [-w limit] [-c limit]
202:
203: Usage:
204: -f, --filename=FILE
205: FILE to load checks from (defaults to /etc/sensorsd.conf)
206: -w, --warning=RANGE or single ENTRY
207: Exit with WARNING status if outside of RANGE or if != ENTRY
208: -c, --critical=RANGE or single ENTRY
209: Exit with CRITICAL status if outside of RANGE or if != ENTRY
210:
211: EOL
1.3 ! andrew 212: print_revision($PROGNAME, '$Revision: 1.2 $');
! 213: }
! 214:
! 215: sub check_max
! 216: {
! 217: my ($num) = @_;
! 218:
! 219: my $state = 'UNKNOWN';
! 220: my $message = 'unknown status';
! 221:
! 222: if (defined $Checks{'max'}{'crit'} && $num > $Checks{'max'}{'crit'}) {
! 223: $state = 'CRITICAL';
! 224: $message = "actual value is ($num) greater than allowed";
! 225: } elsif (defined $Checks{'max'}{'warn'} && $num > $Checks{'max'}{'warn'}) {
! 226: $state = 'WARNING';
! 227: $message = "actual value ($num) is greater than allowed";
! 228: } elsif (defined $Checks{'max'}{'crit'} && defined $Checks{'max'}{'warn'}) {
! 229: $state = 'OK';
! 230: $message = "actual value ($num) is OK";
! 231: }
! 232:
! 233: return $state, $message;
! 234: }
! 235:
! 236: sub check_min
! 237: {
! 238: my ($num) = @_;
! 239:
! 240: my $state = 'UNKNOWN';
! 241: my $message = 'unknown status';
! 242:
! 243: if ($Checks{'min'}{'crit'} && $num < $Checks{'min'}{'crit'}) {
! 244: $state = 'CRITICAL';
! 245: $message = "actual value ($num) is smaller than allowed";
! 246: } elsif (defined $Checks{'min'}{'warn'} && $num < $Checks{'min'}{'warn'}) {
! 247: $state = 'WARNING';
! 248: $message = "actual value ($num) is greater than allowed";
! 249: } elsif (defined $Checks{'min'}{'crit'} && defined $Checks{'min'}{'warn'}) {
! 250: $state = 'OK';
! 251: $message = "actual value ($num) is OK";
! 252: }
! 253:
! 254: return $state, $message;
! 255: }
! 256:
! 257: sub check_delta
! 258: {
! 259: my ($primary, $secondary) = @_;
! 260:
! 261: my $state = 'UNKNOWN';
! 262: my $message = '';
! 263:
! 264: my $delta = 0;
! 265: $delta = ($primary - $secondary) / $primary * 100 if $primary != 0;
! 266: print "Delta: $delta\n";
! 267:
! 268: if (defined $Checks{'change'}{'crit'}
! 269: && abs($delta) > $Checks{'change'}{'crit'}) {
! 270: $state = 'CRITICAL';
! 271: $message = "change ($delta%) is greater than allowed";
! 272: } elsif (defined $Checks{'change'}{'warn'}
! 273: && abs($delta) > $Checks{'change'}{'warn'}) {
! 274: $state = 'WARNING';
! 275: $message = "change ($delta%) is greater than allowed";
! 276: } elsif (defined $Checks{'change'}{'crit'}
! 277: && defined $Checks{'change'}{'warn'}) {
! 278: $state = 'OK';
! 279: $message = "change ($delta%) is OK";
! 280: }
! 281:
! 282: return $state, $message;
1.1 andrew 283: }
284:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>