#!/usr/bin/perl -w

use strict;
use 5.006;
use warnings;

# $Id: monitor.mysql_processlist,v 1.1 2003/12/02 14:43:19 fany Exp $

use DBI     ();
use FindBin ();
use Getopt::Long 'GetOptions';
use Safe ();
use lib $FindBin::Bin;
use noris::NetSaint ();

GetOptions
  'critical=s' => \our @Critical,
  'dsn=s'      => \( our $DSN = 'DBI:mysql:' ),
  'help|?'     => \our $Help,
  'user=s'     => \( our $User = 'proc' ),
  'password=s' => \( our $Password = '' ),
  'warning=s'  => \our @Warning;

exec perldoc => $0 or die "exec(perldoc) returned $?: $!" if $Help;

our $NetSaint = new noris::NetSaint;

sub eval_rules(\%$@) {
    my $process = shift;
    my $status  = shift;
    for (@_) {
        my $safe   = new Safe;
        while(my($k,$v) = each %$process) { ${$safe->varglob($k)} = $v }
        my $result = $safe->reval($_);
        if ( length $@ ) {
            $NetSaint->update( Unknown => qq(error evaluating rule "$_": $@) );
        }
        elsif ($result) { $NetSaint->update( $status => $result ) }
    }
}

my $dbh = DBI->connect( $DSN, $User, $Password, { RaiseError => 1 } )
  or die "Cannot connect to database: $DBI::errstr\n";
my $sth = $dbh->prepare('SHOW PROCESSLIST');
$sth->execute;
while ( defined( my $process = $sth->fetchrow_hashref ) ) {
    eval_rules %$process, Critical => @Critical;
    eval_rules %$process, Warning  => @Warning;
}
$dbh->disconnect;

$NetSaint->update( OK => 'Alles im grnen Bereich.' ) unless $NetSaint->message;

=head1 NAME

monitor.mysql_processlist -- berwachung von MySQL-Prozesslisten

=head1 SYNOPSE

 monitor.mysql_processlist \
     -dsn 'DBI:mysql:host=dbext.noris.net' \
     -warning '$Time > 600 && sprintf("Prozess #%d luft schon seit %.0f Minuten", $Id, $Time/60).(defined $Info && ": $Info")'

=head1 OPTIONEN

Die Optionen werden mittels
L<Getopt::Long::GetOptions()|Getopt::Long/GetOptions> ausgewertet.

=over 4

=item dsn=s

DSN fuer den abzufragenden mysqld; Default: "DBI:mysql:"

=item user=s

Username fuer den Verbindungsaufbau zur Datenbank; Default: "$proc"

=item password=s

Password fuer den Verbindungsaufbau zur Datenbank; Default: ""

=item warning=

Code-Fragment, das auf jede Zeile des mailq-Outputs angewandt wird und eine
Warnung erzeugt, falls es einen wahren Wert zurueckliefert.
Kann mehrfach verwendet werden.

=item critical=s

Code-Fragment, das auf jede Zeile des mailq-Outputs angewandt wird und einen
kritischen Alarm erzeugt, falls es einen wahren Wert zurueckliefert.
Kann mehrfach verwendet werden.

=item help|?

Nur diese Dokumentation ausgeben.

=back

=head1 ANWENDUNG DER -warning- und -critical-REGELN

Alle uebergebenen Regeln werden auf jede Zeile der "SHOW PROCESSLIST"-Ausgabe
des mysqld mittels L<Safe->reval()|Safe/reval> angewandt.

Dabei koennen die Variablen C<$id>, C<$User>, C<$Host>, C<$db>, C<$Command>,
C<$Time>, C<$State> und C<$Info> verwendet werden, die I<vor> der Auswertung
gegen die Werte aus der jeweiligen Zeile ersetzt werden.

Um einen Alarm auszuloesen, muss die Regel einen wahren Wert zurueckgeben,
der gleichzeitig als Alarm-Text verwendet wird.

=head1 AUTOR

 Martin H. Sluka <fany@noris.net>
 fuer die noris network AG

=cut
