summaryrefslogtreecommitdiffstats
path: root/contrib-reporting
diff options
context:
space:
mode:
Diffstat (limited to 'contrib-reporting')
-rw-r--r--contrib-reporting/process_perfdata.pl193
1 files changed, 193 insertions, 0 deletions
diff --git a/contrib-reporting/process_perfdata.pl b/contrib-reporting/process_perfdata.pl
new file mode 100644
index 00000000..c97d4832
--- /dev/null
+++ b/contrib-reporting/process_perfdata.pl
@@ -0,0 +1,193 @@
1#!/usr/local/bin/perl -w
2# author: Al Tobey <albert.tobey@priority-health.com>
3# what: process perfdata from Nagios and put it into RRD files
4# license: GPL - http://www.fsf.org/licenses/gpl.txt
5#
6# Todo:
7# * more documentation (POD) & comments
8# * clean up a bit, make it more configurable - possibly a config file
9
10use strict;
11use lib qw( /opt/nagios/libexec );
12use utils qw( %ERRORS );
13use vars qw( $debug_file %data $debug $rrd_base $process_func $rrd_type );
14use RRDs;
15$debug_file = undef; #"/var/opt/nagios/perfdata.out";
16$rrd_base = '/var/opt/nagios/rrds';
17$process_func = \&process_multi;
18$rrd_type = 'GAUGE';
19$data{hostname} = shift(@ARGV);
20$data{metric} = shift(@ARGV);
21$data{timestamp} = shift(@ARGV);
22$data{perfdata} = join( " ", @ARGV ); $data{perfdata} =~ s/\s+/ /g;
23
24# make sure there's data to work with
25exit $ERRORS{OK} if ( !defined($data{hostname}) || !defined($data{metric})
26 || !defined($data{timestamp}) || !defined($data{perfdata})
27 || $data{perfdata} eq ' ' || $data{perfdata} eq '' );
28
29if ( defined($debug_file) ) {
30 open( LOGFILE, ">>$debug_file" );
31 print LOGFILE "$data{hostname}\t$data{metric}\t$data{timestamp}\t$data{perfdata}\n\n";
32}
33
34# make sure host directory exists
35if ( !-d "$rrd_base/$data{hostname}" ) {
36 mkdir( "$rrd_base/$data{hostname}" )
37 || warn "could not create host directory $rrd_base/$data{hostname}: $!";
38}
39our $rrd_dir = $rrd_base .'/'. $data{hostname};
40
41# --------------------------------------------------------------------------- #
42# do some setup based on the name of the metric
43
44# host data
45if ( $data{metric} eq "HOSTCHECK" ) {
46 $rrd_dir .= '/hostperf';
47}
48# processing disk information
49elsif ( $data{metric} =~ /_DISK$/ ) {
50 $rrd_dir .= '/disk';
51}
52# network interface information
53elsif ( $data{metric} =~ /^IFACE_/ ) {
54 $rrd_dir .= '/interfaces';
55 $rrd_type = [ 'COUNTER', 'COUNTER' ];
56}
57# process performance statistics
58elsif ( $data{metric} =~ /_PROC$/ ) {
59 $rrd_dir .= '/processes';
60 $process_func = \&process_single;
61 $rrd_type = [ 'COUNTER', 'GAUGE' ];
62}
63# a resonable guess
64elsif ( $data{perfdata} =~ /=/ ) {
65 $process_func = \&process_single;
66}
67# everything else
68else {
69 $rrd_dir .= '/other';
70}
71
72# --------------------------------------------------------------------------- #
73# call the proper processing function set up above (functions defined below)
74our @processed = ( $process_func->() );
75
76# --------------------------------------------------------------------------- #
77
78if ( !-d $rrd_dir ) {
79 mkdir( $rrd_dir ) || warn "could not mkdir( $rrd_dir ): $!";
80}
81foreach my $datum ( @processed ) {
82 if ( defined($debug_file) ) {
83 print LOGFILE $datum->{rrd_name}, " = ", join('--',@{$datum->{data}}), "\n"
84 }
85
86 my $rrdfile = $rrd_dir.'/'.$datum->{rrd_name};
87
88 # create the RRD file if it doesn't already exist
89 if ( !-e $rrdfile ) {
90 # create a non-useful datasource title for each "part"
91 RRDs::create( $rrdfile, "-b", $data{timestamp}, "-s", 300, $process_func->($datum, 1),
92 "RRA:AVERAGE:0.5:1:600",
93 "RRA:MAX:0.5:1:600",
94 "RRA:AVERAGE:0.5:6:600",
95 "RRA:MAX:0.5:6:600",
96 "RRA:AVERAGE:0.5:24:600",
97 "RRA:MAX:0.5:24:600",
98 "RRA:AVERAGE:0.5:288:600",
99 "RRA:MAX:0.5:288:600"
100 );
101 if ( my $ERROR = RRDs::error ) { print "ERROR: $ERROR\n"; exit $ERRORS{UNKNOWN}; }
102 }
103 else {
104 # create a template to make sure data goes into the RRD as planned
105 if ( defined($debug_file) ) {
106 print LOGFILE "updating $rrdfile with data:\n\t",
107 join(':', $data{timestamp}, @{$datum->{data}}), "\n";
108 }
109 # update the RRD file
110 RRDs::update( $rrdfile, '-t', $process_func->($datum),
111 join(':', $data{timestamp}, @{$datum->{data}}) );
112 if ( my $ERROR = RRDs::error ) { print "ERROR: $ERROR\n"; exit $ERRORS{UNKNOWN}; }
113 }
114}
115
116# --------------------------------------------------------------------------- #
117
118if ( defined($debug_file) ) {
119 print LOGFILE "-------------------------------------------------------------------------------\n";
120 close( LOGFILE );
121}
122
123exit $ERRORS{OK};
124
125# /opt=value,value,value:/=value,value,value - into multiple rrd's
126sub process_multi {
127 my( $datum, $create ) = @_;
128
129 # return a string for creating new RRDs
130 if ( defined($create) && $create == 1 ) {
131 my @DS = ();
132 for ( my $i=0; $i<scalar(@{$datum->{data}}); $i++ ) {
133 # allow the RRD type to be set in the switch/if above
134 my $tmp_rrd_type = $rrd_type;
135 if ( ref($rrd_type) eq 'ARRAY' ) { $tmp_rrd_type = $rrd_type->[$i] }
136 # put the new datasource into the list
137 push( @DS, "DS:$data{metric}$i:GAUGE:86400:U:U" );
138 }
139 return @DS;
140 }
141 # return a template for updating an RRD
142 elsif ( defined($datum) && !defined($create) ) {
143 my @template = ();
144 for ( my $i=0; $i<scalar(@{$datum->{data}}); $i++ ) {
145 push( @template, $data{metric}.$i );
146 }
147 return join( ':', @template );
148 }
149 # break the data up into parts for processing (updates and creates)
150 else {
151 my @processed = ();
152 foreach my $part ( split(/:/, $data{perfdata}) ) { # break the line into parts
153 my @parts = split( /,/, $part ); # break the part into parts
154 my $rrd_name = $parts[0]; # figure out a good name for the RRD
155 if ( $parts[0] =~ /^\// ) { # handle /'s in disk names
156 $rrd_name = $parts[0];
157 $rrd_name =~ s#/#_#g; $rrd_name =~ s/^_//; $rrd_name =~ s/_$//;
158 if ( $parts[0] eq '/' ) { $rrd_name = 'root' };
159 }
160 # store our munged data in an array of hashes
161 push( @processed, { rrd_name => $rrd_name, name => shift(@parts), data => [ @parts ] } );
162 }
163 return @processed;
164 }
165}
166
167# name=value:name=value - into one rrd
168sub process_single {
169 my( $datum, $create ) = @_;
170
171 my( @names, @values ) = ();
172 foreach my $part ( split(/:/, $data{perfdata}) ) {
173 my( $name, $value ) = split( /=/, $part );
174 push( @names, $name );
175 push( @values, $value );
176 }
177
178 if ( defined($create) && $create == 1 ) {
179 my @DS = ();
180 for( my $i=0; $i<scalar(@names); $i++ ) {
181 my $tmp_rrd_type = $rrd_type;
182 if ( ref($rrd_type) eq 'ARRAY' ) { $tmp_rrd_type = $rrd_type->[$i] }
183 push( @DS, 'DS:'.$names[$i].":$tmp_rrd_type:86400:U:U" );
184 }
185 return @DS;
186 }
187 elsif ( defined($datum) && !defined($create) ) {
188 return join( ':', @names );
189 }
190 else {
191 return( {rrd_name=>lc($data{metric}), name=>$data{metric}, data=>[@values]} );
192 }
193}