From: Guillaume Lelarge Date: Mon, 27 Jun 2011 14:15:54 +0000 (+0200) Subject: Add the hitratio action X-Git-Tag: 2.18.0~45 X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=f46212941807730acbe83128b380a05f91f9ca7f;p=check_postgres.git Add the hitratio action This new action allows a user to track the hit ratio, ie the difference between cache and disk reads, in each database. --- diff --git a/check_postgres.pl b/check_postgres.pl index 7da96ed1d..d745e8572 100755 --- a/check_postgres.pl +++ b/check_postgres.pl @@ -923,6 +923,7 @@ our $action_info = { connection => [0, 'Simple connection check.'], custom_query => [0, 'Run a custom query.'], database_commitratio => [0, 'Report if the commitratio of a database is too low.'], + database_hitratio => [0, 'Report if the hitratio of a database is too low.'], database_size => [0, 'Report if a database is too big.'], dbstats => [1, 'Returns stats from pg_stat_database: Cacti output only'], disabled_triggers => [0, 'Check if any triggers are disabled'], @@ -1575,6 +1576,9 @@ check_connection() if $action eq 'connection'; ## Check the commitratio of one or more databases check_database_commitratio() if $action eq 'database_commitratio'; +## Check the hitratio of one or more databases +check_database_hitratio() if $action eq 'database_hitratio'; + ## Check the size of one or more databases check_database_size() if $action eq 'database_size'; @@ -3638,6 +3642,96 @@ $USERWHERECLAUSE } ## end of check_database_commitratio +sub check_database_hitratio { + + ## Check the hitratio of one or more databases + ## Supports: Nagios, MRTG + ## mrtg reports the largest two databases + ## By default, checks all databases + ## Can check specific one(s) with include + ## Can ignore some with exclude + ## Warning and criticals are percentages + ## Limit to a specific user (db owner) with the includeuser option + ## Exclude users with the excludeuser option + + my ($warning, $critical) = validate_range({type => 'percent'}); + + $SQL = qq{ +SELECT + round(100.*sd.blks_hit/(sd.blks_read+sd.blks_hit), 2) AS dhitratio, + d.datname, + u.usename +FROM pg_stat_database sd +JOIN pg_database d ON (d.oid=sd.datid) +JOIN pg_user u ON (u.usesysid=d.datdba) +WHERE sd.blks_read+sd.blks_hit<>0 +$USERWHERECLAUSE +}; + if ($opt{perflimit}) { + $SQL .= " ORDER BY 1 DESC LIMIT $opt{perflimit}"; + } + + my $info = run_command($SQL, { regex => qr{\d+}, emptyok => 1, } ); + my $found = 0; + + for $db (@{$info->{db}}) { + my $min = 101; + $found = 1; + my %s; + for my $r (@{$db->{slurp}}) { + + next if skip_item($r->{datname}); + + if ($r->{dhitratio} <= $min) { + $min = $r->{dhitratio}; + } + $s{$r->{datname}} = $r->{dhitratio}; + } + + if ($MRTG) { + do_mrtg({one => $min, msg => "DB: $db->{dbname}"}); + } + if ($min > 100) { + $stats{$db->{dbname}} = 0; + if ($USERWHERECLAUSE) { + add_ok msg('no-match-user'); + } + else { + add_unknown msg('no-match-db'); + } + next; + } + + my $msg = ''; + for (reverse sort {$s{$b} <=> $s{$a} or $a cmp $b } keys %s) { + $msg .= "$_: $s{$_} "; + $db->{perf} .= sprintf ' %s=%s;%s;%s', + perfname($_), $s{$_}, $warning, $critical; + } + if (length $critical and $min <= $critical) { + add_critical $msg; + } + elsif (length $warning and $min <= $warning) { + add_warning $msg; + } + else { + add_ok $msg; + } + } + + ## If no results, probably a version problem + if (!$found and keys %unknown) { + (my $first) = values %unknown; + if ($first->[0][0] =~ /pg_database_size/) { + ndie msg('dbsize-version'); + } + } + + return; + +} ## end of check_database_hitratio + + sub check_database_size { ## Check the size of one or more databases @@ -8315,6 +8409,29 @@ Example: Warn if any database on host flagg is less than 90% in commitratio, and For MRTG output, returns the percentage of the database with the smallest commitratio on the first line, and the name of the database on the fourth line. +=head2 B + +(C) Checks the hit ratio of all databases and complains when they are too low. +There is no need to run this command more than once per database cluster. +Databases can be filtered with +the I<--include> and I<--exclude> options. See the L section +for more details. +They can also be filtered by the owner of the database with the +I<--includeuser> and I<--excludeuser> options. +See the L section for more details. + +The warning and critical options should be specified as percentages. There are not +defaults for this action: the warning and critical must be specified. The warning value +cannot be greater than the critical value. The output returns all databases sorted by +hitratio, smallest first. + +Example: Warn if any database on host flagg is less than 90% in hitratio, and critical if less then 80%. + + check_postgres_database_hitratio --host=flagg --warning='90%' --critical='80%' + +For MRTG output, returns the percentage of the database with the smallest hitratio on the first line, +and the name of the database on the fourth line. + =head2 B (C) Checks the size of all databases and complains when they are too big. diff --git a/t/02_database_hitratio.t b/t/02_database_hitratio.t new file mode 100644 index 000000000..5fcd98699 --- /dev/null +++ b/t/02_database_hitratio.t @@ -0,0 +1,85 @@ +#!perl + +## Test the "database_size" action + +use 5.006; +use strict; +use warnings; +use Data::Dumper; +use Test::More tests => 23; +use lib 't','.'; +use CP_Testing; + +use vars qw/$dbh $dbh2 $SQL $count $host $t $result $user/; + +my $cp = CP_Testing->new({default_action => 'database_hitratio'}); + +$dbh = $cp->test_database_handle(); + +my $S = q{Action 'database_hitratio'}; +my $label = 'POSTGRES_DATABASE_HITRATIO'; + +$cp->drop_all_tables(); + +$t=qq{$S returned expected text when warning level is specified in percentages}; +like ($cp->run('-w 0%'), qr{^$label OK:}, $t); + +$t=qq{$S returned expected text when warning level is specified in percentages}; +like ($cp->run('-w 100%'), qr{^$label WARNING:}, $t); + +$t=qq{$S returned expected text when critical level is specified}; +like ($cp->run('-c 0%'), qr{^$label OK:}, $t); + +$t=qq{$S returned expected text when warning level and critical level are specified}; +like ($cp->run('-w 0% -c 0%'), qr{^$label OK:}, $t); + +$t=qq{$S fails when called with an invalid option}; +like ($cp->run('foobar=12'), qr{^\s*Usage:}, $t); + +$t=qq{$S fails when called with an invalid warning option}; +like ($cp->run('-w felz'), qr{^ERROR: Invalid 'warning' option: must be a percentage}, $t); +like ($cp->run('-w 23%%'), qr{^ERROR: Invalid 'warning' option: must be a percentage}, $t); + +$t=qq{$S fails when called with an invalid critical option}; +like ($cp->run('-c felz'), qr{^ERROR: Invalid 'critical' option: must be a percentage}, $t); +like ($cp->run('-c 23%%'), qr{^ERROR: Invalid 'critical' option: must be a percentage}, $t); + +$t=qq{$S fails when the warning or critical percentages is negative}; +like ($cp->run('-w -10%'), qr{^ERROR: Invalid 'warning' option: must be a percentage}, $t); +like ($cp->run('-c -20%'), qr{^ERROR: Invalid 'critical' option: must be a percentage}, $t); + +$t=qq{$S with includeuser option returns nothing}; +like ($cp->run('--includeuser mycatbeda -w 10%'), qr{^$label OK:.+ }, $t); + +$t=qq{$S has critical option trump the warning option}; +like ($cp->run('-w 100% -c 100%'), qr{^$label CRITICAL}, $t); +like ($cp->run('--critical=100% --warning=99%'), qr{^$label CRITICAL}, $t); + +$t=qq{$S returns correct MRTG output when no rows found}; +like ($cp->run('--output=MRTG -w 10% --includeuser nosuchuser'), qr{^101}, $t); + +$t=qq{$S returns correct MRTG output when rows found}; +like ($cp->run('--output=MRTG -w 10%'), qr{\d+\n0\n\nDB: postgres\n}s, $t); + +$t=qq{$S works when include forces no matches}; +like ($cp->run('-w 1% --include blargy'), qr{^$label UNKNOWN: .+No matching databases}, $t); + +$t=qq{$S works when include has valid database}; +like ($cp->run('-w 1% --include=postgres'), qr{$label OK: .+postgres}, $t); + +$t=qq{$S works when exclude excludes nothing}; +like ($cp->run('-w 90% --exclude=foobar'), qr{$label OK: DB "postgres"}, $t); + +$t=qq{$S works when include and exclude make a match}; +like ($cp->run('-w 5% --exclude=postgres --include=postgres'), qr{$label OK: DB "postgres"}, $t); + +$t=qq{$S works when exclude and include make a match}; +like ($cp->run('-w 5% --include=postgres --exclude=postgres'), qr{$label OK: DB "postgres"}, $t); + +$t=qq{$S returned correct performance data with include}; +like ($cp->run('-w 5% --include=postgres'), qr{ \| time=\d\.\d\ds postgres=\d+}, $t); + +$t=qq{$S with includeuser option returns nothing}; +like ($cp->run('--includeuser postgres --includeuser mycatbeda -w 10%'), qr{No matching entries found due to user exclusion}, $t); + +exit;