#!/usr/bin/perl -w

# $Id: check_mysql_processes,v 1.4 2006/07/07 15:27:50 fany Exp $

use 5.006;
use strict;
use warnings;

use DBI ();
use Getopt::Long qw(GetOptions);
use noris::NetSaint;

sub check_relative_threshold($) {
    my ( $option_name, $value ) = @_;
    die "--$option_name akzeptiert nur Werte zwischen 0 und 1.\n"
      if $value < 0 || $value > 1;
    $value;
}

my ( $RelativeCriticalThreshold, $RelativeWarningThreshold );
GetOptions(
    'critical-threshold=i'          => \my $CriticalThreshold,
    'database=s'                    => \my $Database,
    'host=s'                        => \my $Host,
    'password=s'                    => \my $Password,
    'relative-critical-threshold=f' =>
      sub { $RelativeCriticalThreshold = &check_relative_threshold },
    'relative-warning-threshold=f' =>
      sub { $RelativeWarningThreshold = &check_relative_threshold },
    'user=s'              => \my $User,
    'warning-threshold=s' => \my $WarningThreshold,
    'help|?'              =>
      sub { exec perldoc => -F => $0 or die "exec('perldoc -F $0'): $!\n" },
  )
  or exit noris::NetSaint::Status->new('Unknown');

my $netsaint = noris::NetSaint->new;

die "Parameter --database fehlt.\n" unless defined $Database;
warn 'berflssige' . ( @ARGV == 1 && 'r' ) . " Kommandozeilenparameter: @ARGV"
  if @ARGV;

unless (
    my $dbh = DBI->connect(
        "DBI:mysql:database=$Database" . ( defined $Host && ";host=$Host" ),
        $User, $Password, { RaiseError => 1 }
    )
  )
{
    no warnings 'once';
    $netsaint->update(
        Critical => "Konnte keine Datenbankverbindung aufbauen: $DBI::errstr" );
}
elsif (
    defined $RelativeCriticalThreshold || defined $RelativeWarningThreshold
    and !(
        ( undef, my $max_connections ) =
        $dbh->selectrow_array('SHOW VARIABLES LIKE "max_connections"')
    )
  )
{
    $netsaint->update(
        Unknown => 'Kann maximal erlaubte Verbindungsanzahl nicht ermitteln: '
          . $dbh->errstr );
}
else {
    ( undef, my $processes ) =
      $dbh->selectrow_array('SHOW STATUS LIKE "Threads\_connected"');
    unless ( defined $processes ) {
        $netsaint->update( Critical =>
              'Konnte den Wert fr "Threads_connected" nicht ermitteln.' );
    }
    else {
        my $utilisation = $processes / $max_connections
          if defined $max_connections;
        $netsaint->update(
            defined $CriticalThreshold && $processes >= $CriticalThreshold
              || defined $RelativeCriticalThreshold
              && $utilisation >= $RelativeCriticalThreshold ? 'Critical'
            : defined $WarningThreshold && $processes >= $WarningThreshold
              || defined $RelativeWarningThreshold
              && $utilisation >= $RelativeWarningThreshold ? 'Warning'
            : 'OK',
            "$processes Prozess" . ( $processes != 1 && 'e' )
              . (
                defined $utilisation && sprintf " (%.0f %%)",
                100 * $utilisation
              )
        );
    }
}

__END__

=head1 NAME

check_mysql_processes - Anzahl laufender Prozesse eines MySQL-Servers monitoren

=head1 SYNOPSE

  check_mysql_processes                   \
    -host     rz-db-003.brand-ad.noris.de \
    -database monitoring                  \
    -user     monitoring                  \
    -password 'Vagisses(c)!'              \
    -warning-threshold           500      \
    -relative-critical-threshold 0.9

=head1 BESCHREIBUNG

Dieses Plugin berwacht die Anzahl laufender Prozesse (entsprechend der Anzahl
offener Verbindungen) eines MySQL-Datenbank-Servers.

=head1 NOTWENDIGE ARGUMENTE

=over 4

=item database=s

Name einer Datenbank, fr die der Verbindungsaufbau mglich ist.
(Eigentlich geht's hier nicht um eine bestimmte Datenbank, aber L<DBI> ist ohne
unglcklich.)

=back

=head1 OPTIONEN
 
=over 4

=item host=s

zur Angabe des Datenbankservers; Default: lokal

=item user=s

zur Angabe des Benutzernamens fr den Aufbau der Datenbankverbindung

=item password=s

zur Angabe des Kennworts fr den Aufbau der Datenbankverbindung

=item critical-threshold=i

Schwellenwert fr die Anzahl Prozesse, bei dessen berschreiten ein kritischer
Status ausgegeben werden soll

=item warning-threshold=i

Schwellenwert fr die Anzahl Prozesse, bei dessen berschreiten eine Warnung
ausgegeben werden soll

=item relative-critical-threshold=f

relativer Schwellenwert fr die Anzahl Prozesse bezogen auf die auf dem Server
erlaubte Anzahl C<max_connections>, bei dessen berschreiten ein kritischer
Status ausgegeben werden soll

=item relative-warning-threshold=f

relativer Schwellenwert fr die Anzahl Prozesse bezogen auf die auf dem Server
erlaubte Anzahl C<max_connections>, bei dessen berschreiten eine Warnung
ausgegeben werden soll

=item help|?

um (nur) diese Dokumentation anzeigen zu lassen

=back

=head1 AUTOR

 Martin H. Sluka <fany@noris.net>
 fr die noris network AG
 im Rahmen von RT#273924
