#!/usr/bin/perl -w

# $Id: check_newest_logentry,v 1.3 2005/07/05 16:43:56 fany Exp $

use 5.006;
use strict;
use warnings;

{

    package _::undef;
    sub new { bless [], __PACKAGE__ }
    sub readline { }
}

use Date::Parse 'str2time';
use File::ReadBackwards ();
use Getopt::Long 'GetOptions';
use noris::NetSaint ();

GetOptions
  'help|?'             => \our $Help,
  'critical-seconds=i' => \our $CriticalSeconds,
  'date-pattern=s'     => \( our $DatePattern =
'^(\d{4}-\d\d-\d\d \d\d:\d\d:\d\d(?: [+-]\d{4})?|\w\w\w [ 123]\d \d\d:\d\d:\d\d) '
  ),
  'pattern=s' => \( our $Pattern = '.' ),
  'warning-seconds=i' => \our $WarningSeconds;

exec perldoc => $0 or die "exec(perldoc=>'$0'): $!\n" if $Help;

our $NetSaint = new noris::NetSaint;

my $line;
Log: for ( my $fh = new _::undef ; ; ) {
    until ( defined( $line = $fh->readline ) ) {
        my $log;
        unless ( defined( $log = shift ) ) {
            $NetSaint->update(
                Critical => 'Keine passende Log-Zeile gefunden.' );
            last Log;
        }
        $fh = File::ReadBackwards->new($log)
          or die qq(Kann "$log" nicht ffnen: $!\n);
    }
    next unless $line =~ /$Pattern/o;
    unless ( $line =~ /($DatePattern)/o ) {
        $NetSaint->update(
            Unknown => "Kann aus dieser Zeile kein Datum extrahieren: $line" );
    }
    elsif ( !defined( my $time = str2time defined $2 ? $2 : $1 ) ) {
        $NetSaint->update(
            Unknown => "Kann den Datumseintrag nicht parsen: $1" );
    }
    else {
        my $age = $^T - $time;
        $NetSaint->add_message(
                "Die neueste passende Log-Zeile ist $age Sekunde"
              . ( $age != 1 && 'n' )
              . ' alt.' );
        if ( defined $CriticalSeconds && $age > $CriticalSeconds ) {
            $NetSaint->atleast('Critical');
        }
        elsif ( defined $WarningSeconds && $age > $WarningSeconds ) {
            $NetSaint->atleast('Warning');
        }
        else { $NetSaint->atleast('OK') }
    }
    last;
}

=head1 NAME

check_newest_logentry -- Nagios-Plugin zur Suche nach Log-Eintrgen

=head1 SYNOPSE

  check_newest_logentry --warning 1260 --critical 2520 \
    --pattern      ' => PB_mit_FaP@norisbank\.de ' \
    --date-pattern '^(\d{4}-\d\d-\d\d \d\d:\d\d:\d\d(?: [+-]\d{4})?|\w\w\w [ 123]\d \d\d:\d\d:\d\d) /' \
    /var/log/exim/mainlog{,.0}

Durchsucht L<rckwrts|File::ReadBackwards> die angegebenen Log-Dateien (aber
jede fr sich rckwrts. d. h. hier zuerst C</var/log/exim/mainlog>, dann ggf.
C</var/log/exim/mainlog.0>), bis es auf einen Eintrag stt, der auf den
angegebenen I<--pattern> passt.
Aus dieser Zeile versucht es dann mit Hilfe des I<--date-pattern> einen
Timestamp zu extrahieren und so das Alter des Log-Eintrags (relativ zum
Startzeitpunkt des Plugins) zu ermitteln.
berschreitet dieses Alter die mittels I<--critical-seconds> und/oder
I<--warning-seconds> angegebenen Schwellenwerte, so wird ein eintsprechender
Alarmzustand erzeugt.

Der Defaultwert fr I<--pattern> ist ".", also effektiv die letzte nicht leere
Log-Zeile berhaupt.
Der Defaultwert fr I<--date-pattern> entspricht dem im Beispiel verwendeten
Optionswert.

=head1 AUTOR

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

=cut

