#!/usr/bin/perl -w
use strict;
use DBI;

my $dbhost=$ARGV[0] || die "Pass the IP or hostname of a postgresql server to check.";
my $dbname=$ARGV[1] || 'template1';
my $dbuser=$ARGV[2] || 'postgres';
my $dbpass=$ARGV[3] || '';

# 2000M = 2 Billion. Too many zeros hurt my eyes.
my $wrap_xid_M=2000; # Record wrap at 2 Billion
my $warn_xid_M=1000; # Warn at 1.0 Billion
my $crit_xid_M=1500; # Critical at 1.5 Billion

my $status=3;        # default to an UNKNOWN status
my $max_xid_pct=-99; # default to a negative percentage
my $max_xid_M=-9999; # default to negative XID #
my $max_xid_datname="NOT SET (script broke)";

my $Con = "DBI:Pg:dbname=$dbname;host=$dbhost";
my $Dbh = DBI->connect($Con, $dbuser, $dbpass, {RaiseError =>1}) || die "Unable to access Database $dbname on host $dbhost as user $dbuser.\nError returned was: ". $DBI::errstr;

my $sql="SELECT datname, age(datfrozenxid) FROM pg_database;";
my $sth = $Dbh->prepare($sql);
$sth->execute();
while (my ($datname,$max_xid) = $sth->fetchrow()) {
  my $xid_used_M=sprintf('%1d',($max_xid/1000000));
  my $xid_used_pct=sprintf('%1d', ($xid_used_M/$wrap_xid_M)*100);
  #find the database with the highest transaction id
  if ($xid_used_M > $max_xid_M)
  {
    $max_xid_pct=$xid_used_pct;
    $max_xid_M=$xid_used_M;
    $max_xid_datname=$datname;
  }
}
$Dbh->disconnect;

# 3 UNKNOWN, 2 CRITICAL, 1 WARNING, 0 OK
if ($max_xid_M >= $crit_xid_M)
{
    $status=2;
}
elsif ($max_xid_M >= $warn_xid_M)
{
    $status=1;
}
elsif ($max_xid_M < $warn_xid_M && $max_xid_M > 0 )
{
    $status=0;
}
else
{
    #This means something is wrong with the query or math above
    $status=3;
}

print "Transaction IDs are $max_xid_pct% used ($max_xid_M M) in database $max_xid_datname.\n";
exit $status;


