package Monitor::cpuload;

###############################################################################
# $Header: /cvsroot/bigsister/bigsister/uxmon/Monitor/cpuload.pm,v 1.14 2003/07/11 13:08:52 aeby Exp $
#
# Zweck: 
###############################################################################
# $Log: cpuload.pm,v $
# Revision 1.14  2003/07/11 13:08:52  aeby
# (Andreas Jordan): fixed top usage: the first time top is called it does not
# report correct CPU usage
#
# Revision 1.2  2002/08/21 12:56:56  mg
# Initiale ORDIX Version mit CVS-Headern
#
###############################################################################


# Neue Version:
# Da der Aufruf von "top" erst nach einiger Zeit korrekte Werte liefert,
# wird in dieser Version der "top" zwei Mal gestartet und nur das zweite
# Ergebnis benutzt.
# Änderungen von Stefan Koch, ORDIX AG (sk@ordix.de)


require 5.002;

#use strict;

@Monitor::cpuload::ISA = qw(Monitor::Monitor);

# create the objects + memory space needed
sub new
{

    my ($this, $pscomm) = @_;
    my  $class = ref($this) || $this;
    my  $self = {};

    bless($self, $class);

    # create an array to store the CPU load limits info
    $self->{"htable"} = [];

    return($self);
}


sub add_check 
{
    my( $self, $max1, $max2, $item ) = @_;
    my( $htable ) = $self->{"htable"};

    # figure out how to report this data ( server name + monitor name )
    ($item = $uxmon::hostname.".cpu") unless( $item );

    # report on what's going on - if we're in debug mode
    if( $BigSister::common::dl>3 )
    {
        print "add_check - item: '$item'\n";
    }

    # add this info to the configuration array
    push( @$htable, join( "\x00", $item, $max1, $max2 ) );
}


sub check
{
    my ($self) = @_;

    my( $htable ) = $self->{"htable"};

    # get the cpu load averages using 'uptime'
    my $uptime;
### Alte Version:
#    my @top = `top -n 1 -b`;
#    my $top = join("",@top[0 .. 31]);

### Neu Version:
# Da top beim ersten Mal nicht die richtigen Werte anzeigt: mit n 2 Mal aufrufen:
    my @top = `top -n 2 -b`;
    my $top;


# Die erste Ausgabe wegschmeißen
{
my($gefunden)=0;
for(my $i=0; $i <= $#top; $i++) {
        if (!$gefunden && $top[$i] !~ /load average:/ ) { $top[$i]=""; next; }
        if (!$gefunden && $top[$i] =~ /load average:/ ) { $gefunden=1;  $top[$i]=""; next;}
        if ($gefunden && $top[$i] !~ /load average:/ )  { $top[$i]=""; next;}
        $top=join("", @top[$i .. ($i+31)]);
        last;
}
print "$top\n";
}		

# Ab hier kann man die top-Ausgabe wieder verwenden:
### Ende der Änderungen

    if( $top =~ /^(.*users,\s*load average.*)$/m ) {
	print "Uptime retrieved from top\n";
	$uptime = $1."\n";
    } else {
	print "Running uptime command\n";
	$uptime = `uptime`;
    } 

    # report on what's going on - if we're in debug mode
    if( $BigSister::common::dl>3 )
    {
         print "uptime: '$uptime'\n";
    }

    # retrieve the data from the info returned by uptime
    $uptime =~ /load average.{0,1}: (.+)$/;
    my $loads = $1;

    # report on what's going on - if we're in debug mode
    if( $BigSister::common::dl>3 )
    { 
        print "load: '$loads'\n";
    }

    # now split the data into it's three numeric components
    my ($load1,$load2, $load3);

    ($load1,$load2, $load3) = split (',',$loads);

    # report on what's going on - if we're in debug mode
    if( $BigSister::common::dl>3 )
    {
        print "load1: '$load1'\n";
        print "load2: '$load2'\n";
        print "load3: '$load3'\n";
    }
    $self->set_variable( "", "cpu.load.uptime.0", $load1 );
    $self->set_variable( "", "cpu.load.uptime.1", $load2 );
    $self->set_variable( "", "cpu.load.uptime.2", $load3 );

    # Use the 1 minute load average for tests.
    my $ave = $load1;
    $self->set_variable( "", "cpu.load.uptime.avg", $ave );

    # loop throught every item to be checked (probably only one per box)
    for( $i=0; $i<=$#$htable; $i++ ) 
    {
        ( $item, $max1, $max2 ) = split( "\x00", $$htable[$i] );

        # report on what's going on - if we're in debug mode
        if( $BigSister::common::dl>3 )
        {
            print "working on '$i' : item: '$item' max1:'$max1' max2:'$max2'\n";
        }

        #  check for errors
        if (! length($ave) )
        {
            # report to main monitoring server the status
            $self->report( $item, $BigSister::common::status_codes{"yellow"}, "CPU load average - no data from 'uptime'" );
               
            # report on what's going on - if we're in debug mode
            if( $BigSister::common::dl>3 )
            {
                print "CPUload error! (couldn't get data from 'uptime')\n";
            }
        }
        else
        {
            # see how to report on CPU load - red, yellow or GREEN
            if( (length($max2) && ($ave>$max2)) ) {
                $self->report( $item, $BigSister::common::status_codes{"red"}, "CPU load >>($ave)" );
            }
            elsif( (length($max1) && ($ave>$max1)) ) {
                $self->report( $item, $BigSister::common::status_codes{"yellow"}, "CPU load >($ave)" );
            }
            else {
                $self->report( $item, $BigSister::common::status_codes{"green"}, "CPU load = $ave" );
            }
            
            # report on what's going on - if we're in debug mode
            if( $BigSister::common::dl>3 )
            {
                print "Made it through cpuload.pm::check just fine - ";
                print "CPUload worked!\n";
            }
        }
	$self->report( $item, 100, $uptime ) if ($uptime && !$top);
	$self->report( $item, 100, $top ) if ($top);
	print "Uptime result: $item, 100, $uptime\n" if ($BigSister::common::dl);
    }

}

1;
