#!/usr/bin/perl -w package PerfDataConsumers; use strict; use RRDPerf qw/update_rrd graph_rrd/; my $debug = 0; BEGIN{ use Exporter (); @PerfDataConsumers::ISA = qw(Exporter); @PerfDataConsumers::EXPORT = qw(); @PerfDataConsumers::EXPORT_OK = qw(%consumers %graphers); } =head1 NAME PerfDataConsumers.pm - PerfData handlers, user expandable. =head1 AUTHOR (c) 2003 Hannes Schulz =head1 VERSION Version 1.0 =head1 SYNOPSIS This module provides functions for consuming performance data created by Nagios. It is supposed to be easily expandable for later use(r)s. For every service you want to create a graph for, put a consumer and a graph function in here and note the service description and the function ref in the hash (see VARIABLES). =head2 DEBUGGING Set C<$debug> to true in the script. If your crontab has a line MAILTO=you@sap.com you should get the results by mail every hour. =head2 EXAMPLE sub consume_ping{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $outp; my ($loss,$rta) = m/loss = ([\d\.]+)%, RTA = ([\d\.]+) ms/; unless (defined $loss && defined $rta){ warn "$hn: Error while parsing $sdesc: $perf\n" if($debug); return; } update_rrd($sdesc,$hn, 900, $timet, "loss", $loss, "RTA", $rta ); } sub graph_ping{ my ($sdesc, $hostname) = @_; graph_rrd($sdesc, $hostname,"Ping-Statistics","loss","RTA"); } $graphers{"PING"} = \&graph_ping; $consumers{"PING"} = \&consume_ping; =head1 DESCRIPTION This is middleware between C and RRPerf.pm. It is designed to be easily expandable, the only thing you WILL have to do is parse the performance output into variables and hand them over to the L-functions. See there for details/parameters. You MAY want to do as complicated things as we did for "Logon Totals", but it I. =head1 CAVEATS Watch your spelling. $graphers{"PING"} = \&graph_ping; is entirely different than $graphers{"PINg"} = \&graph_ping; and won't work at all. =head2 VARIABLES =over 4 =item %consumers contains a list of all consumers in this Module and references to the subs handling them: %consumers = ("PING" => \&consume_ping); =cut our %consumers = (); =item %graphers contains a list of all graphers in this Module and references to the subs handling them: %graphers = ("PING" => \&graph_ping); =cut our %graphers = (); =back =head2 METHODS =over 4 =item PING {{{1 graphs for loss and RTA =cut sub consume_ping{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $outp; my ($loss,$rta) = m/loss = ([\d\.]+)%, RTA = ([\d\.]+) ms/; unless (defined $loss && defined $rta){ warn "$hn: Error while parsing $sdesc: $perf\n" if($debug); return; } warn "$sdesc($hn): loss = $loss, rta = $rta \n" if($debug); update_rrd($sdesc,$hn, 900, $timet, "loss", $loss, "RTA", $rta ); } sub graph_ping{ my ($sdesc, $hostname) = @_; graph_rrd($sdesc, $hostname,"Ping-Statistics","loss","RTA"); } $graphers{"PING"} = \&graph_ping; $consumers{"PING"} = \&consume_ping; =item Outbound Bytes Total Since Boot {{{1 graphs for Outbound Bytes Total Since Boot =cut sub consume_draoutbbytes{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $outp; my ($hour,$day) = m/hour=(\d+) day=(\d+)\s*$/; unless (defined $day and defined $hour){ warn "$hn: Error while parsing $sdesc: $outp\n" if($debug); return; } warn "$sdesc($hn): $day, $hour \n" if($debug); update_rrd("draoutbbytes",$hn, 900, $timet, "hour_MB_times_10", 10*$hour/1048576, "day_MB", $day/1048576 ); } sub graph_draoutbbytes{ my ($sdesc, $hostname) = @_; graph_rrd("draoutbbytes", $hostname,"DRA Outbound Bytes Total Since Boot", "day_MB","hour_MB_times_10"); } $graphers{"DRA Outbound Bytes"} = \&graph_draoutbbytes; $consumers{"DRA Outbound Bytes"} = \&consume_draoutbbytes; =item Inbound Bytes Total Since Boot {{{1 graphs for Inbound Bytes Total Since Boot =cut sub consume_drainbbytes{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $outp; my ($hour,$day) = m/hour=(\d+) day=(\d+)\s*$/; unless (defined $day and defined $hour){ warn "$hn: Error while parsing $sdesc: $outp\n" if($debug); return; } warn "$sdesc($hn): $day, $hour \n" if($debug); update_rrd("drainbbytes",$hn, 900, $timet, "hour_MB_times_10", 10*$hour/1048576, "day_MB", $day/1048576 ); } sub graph_drainbbytes{ my ($sdesc, $hostname) = @_; graph_rrd("drainbbytes", $hostname,"DRA Inbound Bytes Total Since Boot", "day_MB","hour_MB_times_10"); } $graphers{"DRA Inbound Bytes"} = \&graph_drainbbytes; $consumers{"DRA Inbound Bytes"} = \&consume_drainbbytes; =item LogonTotalALL {{{1 logon total for ALL hosts. =cut sub consume_logontotalall{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $outp; my ($dval,$l24) = m/all=(\d+)\sday=(\d+)\s*$/o; unless (defined $dval and defined $l24){ warn "$hn: Error while parsing $sdesc: $outp\n" if($debug); return; } warn "$sdesc($hn): dval = $dval day=$l24\n" if($debug); update_rrd($sdesc,$hn, 3600, $timet, "logons", $dval ); update_rrd("$sdesc-day",$hn, 3600, $timet, "logons_last_24h", $l24 ); } sub graph_logontotalall{ my ($sdesc, $hostname) = @_; graph_rrd($sdesc, $hostname,"All Hosts Logon Statistics","logons"); graph_rrd("$sdesc-day", $hostname,"All Hosts Logons in 24h window","logons_last_24h"); } $graphers{"logonALL"} = \&graph_logontotalall; $consumers{"logonALL"} = \&consume_logontotalall; =item W2K-Memuse {{{1 graphs for Memory use on W2K =cut sub consume_w2kmem{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $outp; my ($used) = m/used:.*? \((\d+)%\)$/; unless (defined $used){ warn "$hn: Error while parsing $sdesc: $outp\n" if($debug); return; }; warn "$sdesc($hn): used = $used\n" if($debug); update_rrd($sdesc,$hn, 1800, $timet, "used_perc", $used ); } sub graph_w2kmem{ my ($sdesc, $hostname) = @_; graph_rrd($sdesc, $hostname,"W2K-Memory-Statistics","used_perc"); } $graphers{"W2K-MemUse"} = \&graph_w2kmem; $consumers{"W2K-MemUse"} = \&consume_w2kmem; =item DNS {{{1 graphs for DNS-Query-time =cut sub consume_dns{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $perf; my ($tm) = m/DurationMS=(\d+)$/; unless (defined $tm){ warn "$hn: Error while parsing $sdesc: $perf\n" if($debug); return; }; warn "$sdesc($hn): duration = $tm ms\n" if($debug); update_rrd($sdesc,$hn, 1800, $timet, "time_ms", $tm ); } sub graph_dns{ my ($sdesc, $hostname) = @_; graph_rrd($sdesc, $hostname,"DNS-Statistics","time_ms"); } $graphers{"DNS-Query"} = \&graph_dns; $consumers{"DNS-Query"} = \&consume_dns; =item W2K-CPU {{{1 graphs for CPU on W2K =cut sub consume_w2kcpu{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $perf; my ($cpu1,$cpu2,$cpu3) = m/:(\d+) .*:(\d+) .*:(\d+)\s*$/; unless (defined $cpu1 and defined $cpu2 and defined $cpu3){ warn "$hn: Error while parsing $sdesc: $perf\n" if($debug); return; }; warn "$sdesc($hn): cpu = $cpu1, $cpu2, $cpu3\n" if($debug); update_rrd($sdesc,$hn, 1800, $timet, "last10min", $cpu1, "last60min", $cpu2, "last24hours", $cpu3 ); } sub graph_w2kcpu{ my ($sdesc, $hostname) = @_; graph_rrd($sdesc, $hostname,"W2K-CPU-Statistics", "last10min", "last60min", "last24hours"); } $graphers{"W2K-CPU"} = \&graph_w2kcpu; $consumers{"W2K-CPU"} = \&consume_w2kcpu; # }}}1 =item W2K-Drive-C {{{1 graphs for Disk C use on W2K =cut sub consume_w2kdrivec{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $outp; my ($used) = m/used: [\d\.]+ \w+ \((\d+)%\) -/; if (!defined $used){ warn "$hn: Error while parsing $sdesc: $outp\n" if($debug); return; }; warn "$sdesc: used = $used \n" if($debug); update_rrd($sdesc,$hn, 1800, $timet, "used_perc", $used ); } sub graph_w2kdrivec{ my ($sdesc, $hostname) = @_; graph_rrd($sdesc, $hostname,"W2K-Drive-C-Statistics","used_perc"); } $graphers{"Disk Usage Drive C"} = \&graph_w2kdrivec; $consumers{"Disk Usage Drive C"} = \&consume_w2kdrivec; # }}}1 =item W2K-Drive-D {{{1 graphs for Disk D use on W2K =cut sub consume_w2kdrived{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $outp; my ($used) = m/used: [\d\.]+ \w+ \((\d+)%\) -/; if (!defined $used){ warn "$hn: Error while parsing $sdesc: $outp\n" if($debug); return; }; warn "$sdesc($hn): used = $used \n" if($debug); update_rrd($sdesc,$hn, 1800, $timet, "used_perc", $used ); } sub graph_w2kdrived{ my ($sdesc, $hostname) = @_; graph_rrd($sdesc, $hostname,"W2K-Drive-D-Statistics","used_perc"); } $graphers{"Disk Usage Drive D"} = \&graph_w2kdrived; $consumers{"Disk Usage Drive D"} = \&consume_w2kdrived; # }}}1 =item Logon Total {{{1 graphs for the total logons on some computer =cut sub consume_totallogon{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; my($hour,$day) = ($outp =~ m/hour=(\d+) day=(\d+)\s*$/); unless(defined $hour and defined $day){ warn "$hn: Error while parsing $sdesc: $outp\n" if($debug); return; } warn "$sdesc($hn): $hour, $day \n" if($debug); update_rrd($sdesc,$hn, 3600, $timet, "per_hour_times_10", $hour*10, "per_day", $day ); } sub graph_totallogon{ my ($sdesc, $hostname) = @_; graph_rrd($sdesc, $hostname,"Total-Logon-Statistics", "per_day","per_hour_times_10"); } $graphers{"logon-total"} = \&graph_totallogon; $consumers{"logon-total"} = \&consume_totallogon; =item Performance-NRPEP {{{1 graphs for NRPEP-Performance (Load, CPU, Memory/Swap) =cut sub consume_perfnrpep{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $perf; my @data = split /@/; my $d; foreach $d (@data){ if(my ($t,$min1,$min5,$min15) = ($d =~ m/^\s*uptime!(\d+):([\d\.]+):([\d\.]+):([\d\.]+)\s*$/o)){ warn "uptime($hn): $min1, $min5, $min15 \n" if($debug); update_rrd("load-$sdesc",$hn, 900, $t, "load_perc_1min", $min1, "load_perc_5min", $min5, "load_perc_15min", $min15 ); } elsif(my ($t2,$usr,$sys,$idle) = ( $d =~ m/^\s*cpu!(\d+):(\d+):(\d+):(\d+)\s*$/o)){ warn "cpu($hn): $usr, $sys, $idle \n" if($debug); update_rrd("cpu-$sdesc",$hn, 900, $t2, "cpu_perc_usr", $usr, "cpu_perc_sys", $sys, "cpu_perc_idls", $idle ); } elsif(my ($t3,$totm,$usem,$tots,$uses) = ( $d =~ m/^\s*mem!(\d+):(\d+):(\d+):(\d+):(\d+)\s*$/o)){ warn "cpu($hn): $totm, $usem, $tots, $uses \n" if($debug); update_rrd("mem-$sdesc",$hn, 900, $t3, "mem_perc_mem", 100*$usem/$totm, "mem_perc_swap", 100*$uses/$tots ); } } } sub graph_perfnrpep{ my ($sdesc, $hostname) = @_; graph_rrd("load-$sdesc", $hostname, "Load Average", "load_perc_1min", "load_perc_5min", "load_perc_15min" ); graph_rrd("cpu-$sdesc", $hostname, "CPU load", "cpu_perc_usr", "cpu_perc_sys", "cpu_perc_idls" ); graph_rrd("mem-$sdesc", $hostname, "Memory Usage", "mem_perc_mem", "mem_perc_swap" ); } $graphers{"perf-nrpep"} = \&graph_perfnrpep; $consumers{"perf-nrpep"} = \&consume_perfnrpep; # }}}1 =item Disk-NRPEP {{{1 graphs for NRPEP-Diskspace (all drives) =cut sub consume_disknrpep{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; $_ = $perf; my @data = split /@/; my @tosav = (); my $d; my ($drive,$t,$used,$avail); open(DRIVES, ">/usr/local/nagios_indep/var/rrds/$hn/drives.txt"); foreach $d (@data){ if(($drive,$t,$used,$avail) = ($d =~ m/^\s*fs:(.+)!(\d+):(\d+):(\d+)\s*$/o)){ warn "fs($hn): $used, $avail\n" if($debug); $drive =~ y!/!_!; $drive =~ s!^/(.*)$!$1!; push @tosav, $drive, (100*$used/($used+$avail)); print DRIVES "$drive\n" } } close DRIVES; update_rrd("fs-$sdesc",$hn, 1800, $t, @tosav ); } sub graph_disknrpep{ my ($sdesc, $hn) = @_; my @drives = (); open(DRIVES, "){ chomp; push @drives, $_ } close DRIVES; graph_rrd("fs-$sdesc", $hn, "File System Usage (%)", @drives ); } $graphers{"disk-nrpep"} = \&graph_disknrpep; $consumers{"disk-nrpep"} = \&consume_disknrpep; # }}}1 =item BIND-stats {{{1 graphs for the BIND-statistics =cut sub consume_bindstats{ my ($timet,$sdesc,$hn,$outp,$perf) = @_; my ($ls) = ($outp =~ /aqueries=(\d+)\b/); return if($ls !~ m/^\d+$/o); my $lphfile = "/usr/local/nagios_indep/var/rrds/$hn/qph.txt"; my $lpdfile = "/usr/local/nagios_indep/var/rrds/$hn/qpd.txt"; my $tofile = "/usr/local/nagios_indep/var/rrds/$hn/toffset.txt"; unless (defined $ls){ warn "$hn: Error while parsing $sdesc: $perf\n" if($debug); return; } warn "$sdesc($hn): $ls \n" if($debug); my ($lph,$lpht) = split /:/,`cat $lphfile 2>/dev/null`; my ($lpd,$lpdt) = split /:/,`cat $lpdfile 2>/dev/null`; my $to = `cat $tofile`; # Maybe create new files... {{{ if(!defined $lph){ $lph = $ls; $lpht = $timet; `echo "$ls:$timet" > $lphfile`; } if(!defined $lpd){ $lpd = $ls; $lpdt = $timet; `echo "$ls:$timet" > $lpdfile`; } # }}} my ($hval, $dval); # save value per-hour if defined only! {{{ if(($timet - $lpht)){ $hval = ($ls - $lph) / (($timet - $lpht)/3600); $hval = ($hval > 0)? $hval : 0 }else{ $hval = 0; } # }}} # update file if we're over the period {{{ if(($timet -$lpht) > 3600){ `echo "$ls:$timet" > $lphfile`; } # }}} # save value per-day if defined only! {{{ if(($timet - $lpdt)){ $dval = ($ls - $lpd); $dval = ($dval > 0)? $dval : 0 }else{ $dval = 0; } # }}} # update file if we're at a different DAY. {{{ if((localtime($lpdt + ($to * 3600)))[3] != (localtime($timet + ($to * 3600)))[3]){ `echo "$ls:$timet" > $lpdfile`; } # }}} update_rrd($sdesc,$hn, 3600, $timet, "per_hour_times_10", $hval*10, "per_day", $dval ); } sub graph_bindstats{ my ($sdesc, $hostname) = @_; graph_rrd($sdesc, $hostname,"BIND-Statistics", "per_day","per_hour_times_10"); } $graphers{"bind-stats"} = \&graph_bindstats; $consumers{"bind-stats"} = \&consume_bindstats; =back =cut 1; # vim:fdm=marker