#!/usr/bin/perl -w

=head1 NAME

PerfDataConsumer.pl - reads F<serviceperf.log>, runs handlers from L<PerfDataConsumers.pm>.

=head1 VERSION

Version 1.0

=head1 AUTHOR

(c) 2003 Hannes Schulz <mail@hannes-schulz.de>

=head1 SYNOPSIS

  ./PerfDataConsumer.pl

=head1 DESCRIPTION

This reads the performance log, updates the rrd files with the data from it,
and in the end creates graphs that visualize the data in the database.

=head1 CONFIGURATION

If paths change set the variables at the top of the script accordingly.
No other config should be needed in here. To add counters and visualization
data take a look at the documentation of L<PerfDataConsumers.pm>!

=head1 DEBUGGING

If you believe something here goes wrong, you I<might> want to think about
setting C<$debug> at the start of the script to a true value, and call this
script like this:

  ./PerfDataConsumer.pl 2>&1 | less -S

If your crontab has a line

  MAILTO=you@sap.com

you should get the results by mail every hour. Same thing for
L<PerfDataConsumers.pm> and L<RRDPerf.pm>.

=cut

use lib '/usr/local/nagios_indep/bin';

use strict;
use PerfDataConsumers qw/%consumers %graphers/;

my $debug = 0;

if($debug){
	print "$0: Found handlers for the following services: ";
	print join(", ", keys %consumers);
	print ".\n";
};

my $pdo = "/usr/local/nagios_indep/var/serviceperf.log";
my $pd  = "/usr/local/nagios_indep/var/serviceperf.log_tmp";

my (%found_hosts, %found_services);

# Don't overwrite the temp file.
if (-e $pd){
	die "$pd already exists! Last run not done yet?\n";
};

# Quickly (!) remove original File and put empty one there instead
`mv $pdo $pd ; touch $pdo ; chmod a+w $pdo ; /etc/init.d/nagiosM reload >/dev/null 2>&1`;

open(PD, "<$pd") || die "Could not open $pd: $!\n";

my ($timet,$sdesc,$hn,$outp,$perf);
while(<PD>){
  ($timet,$sdesc,$hn,$outp,$perf) = split /\t/;
  unless(handleData($timet, $sdesc, $hn, $outp, $perf)){
	print "Could not parse line $_!\n" if $debug;
	next;
  };
  $found_hosts{$hn} = 1;
  $found_services{$sdesc} = 1;
}

my ($h, $s);
foreach $h (keys %found_hosts){
	foreach $s (keys %found_services){
		unless(graphData($s, $h)){
			print "could not draw $s for $h.\n" if $debug;
		}
	}
}

=head1 METHODS

=over 4

=item graphData

This method uses the hash C<%graphers> derived from L<PerfDataConsumers.pm> to
figure out which function to call for a specific data line in
C<serviceperf.log>.

Usage:

  graphData($sdesc,$hostname);

where 

C<$sdesc> is the name of the service as it appears in C<serviceperf.log>

C<$hostname> is the (short) name of the host as configured in C<hosts.cfg> and
as it appears in C<serviceperf.log>.

=cut

sub graphData{
	my ($sdesc,$host) = @_;

	foreach(@_){ return 0 if (!defined $_); }    # check args
	return 0 unless defined($graphers{$sdesc});  # check if defined
	&{$graphers{$sdesc}};
	return 1;
}

=item handleData

This method uses the hash C<%consumers> derived from L<PerfDataConsumers.pm>
to figure out which function to call for a specific data line in
C<serviceperf.log>.

Usage:

  handleData($timet,$sdesc,$hostname,$outp,$perf);

where 

C<$timet> is the (UNIX-) time when the mesure was taken (seconds since 1970)

C<$sdesc> is the name of the service as it appears in C<serviceperf.log>

C<$hostname> is the (short) name of the host as configured in C<hosts.cfg> and
as it appears in C<serviceperf.log>.

C<$outp> is the output created by the C<check_>-module used to take the mesure

C<$perf> is the Performance data created by exactly the same module.

B<All this data pretty much should resemble one line in> C<serviceperf.log>.

=cut

sub handleData{
	my ($timet,$sdesc,$hn,$outp,$perf) = @_;

	foreach(@_){ return 0 if (!defined $_); }
	return 0 unless (defined $consumers{$sdesc});
	&{$consumers{$sdesc}}(@_);
	return 1;
}

`rm $pd`;
