2014-01-07 17:13:40 +01:00
|
|
|
#!/usr/bin/perl
|
|
|
|
# vim: set filetype=perl sw=4 tabstop=4 expandtab smartindent: #
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
|
|
|
postfwd2 - plugin to get stats from postfwd2
|
|
|
|
|
|
|
|
=head1 AUTHOR AND COPYRIGHT
|
|
|
|
|
2014-01-07 17:22:21 +01:00
|
|
|
Copyright 2013-2014 Luc Didry <luc AT didry.org>
|
2014-01-07 17:13:40 +01:00
|
|
|
|
|
|
|
=head1 HOWTO CONFIGURE AND USE :
|
|
|
|
|
|
|
|
=over
|
|
|
|
|
|
|
|
=item - /etc/munin/plugin-conf.d/postfwd2
|
|
|
|
|
|
|
|
[postfwd2]
|
|
|
|
user root
|
|
|
|
env.path /usr/local/sbin/postfwd2 # OPTIONAL : looks for postfwd2 in /bin, /sbin, /usr/bin, /usr/sbin, /usr/local/bin, /usr/local/sbin
|
|
|
|
env.include .*ISBAD #OPTIONAL
|
|
|
|
env.exclude .*ISGOOD #OPTIONAL
|
|
|
|
|
|
|
|
=item - env.include and env.exclude
|
|
|
|
|
|
|
|
This are perl regexp.
|
|
|
|
If env.include is set and env.exclude is not, only the policy which name
|
|
|
|
matchs will be used.
|
|
|
|
If env.exclude is set and env.include is not, only the policy which name NOT
|
|
|
|
matchs will be used.
|
|
|
|
If both are set, a policy which name matchs the both regex will be used, a
|
|
|
|
policy which matchs only the exclude regexp will NOT be used and a policy
|
|
|
|
which match not the exclude regex will be used, even if it not matchs the
|
|
|
|
include regexp.
|
|
|
|
if none are set, all the policy will be used.
|
|
|
|
|
|
|
|
|
|
|
|
=item - /etc/munin/plugins
|
|
|
|
|
|
|
|
cp postfwd2 /etc/munin/plugins
|
|
|
|
|
|
|
|
|
|
|
|
=item - restart Munin node
|
|
|
|
|
|
|
|
service munin-node restart
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
=head1 LICENSE
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify it under
|
|
|
|
the terms of the GNU General Public License as published by the Free Software
|
|
|
|
Foundation, either version 3 of the License, or any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
|
|
|
use warnings;
|
|
|
|
use strict;
|
|
|
|
use Munin::Plugin;
|
|
|
|
|
|
|
|
need_multigraph();
|
|
|
|
|
|
|
|
my @keys =qw/cache_queries cache_stats policy_requests policy_timeout policy_matchs/;
|
|
|
|
my %graphs = (
|
|
|
|
cache_queries => {
|
|
|
|
title => 'Cache queries',
|
|
|
|
vlabel => 'Nb of cache queries',
|
|
|
|
series => {
|
|
|
|
cache_queries => {
|
|
|
|
label => 'Cache queries',
|
|
|
|
type => 'COUNTER'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
cache_stats => {
|
|
|
|
title => 'Cache stats',
|
|
|
|
vlabel => 'percent',
|
|
|
|
series => {
|
|
|
|
cache_requests => {
|
|
|
|
label => 'Requests hitrate',
|
|
|
|
type => 'GAUGE'
|
|
|
|
},
|
|
|
|
cache_dns => {
|
|
|
|
label => 'Dns hitrate',
|
|
|
|
type => 'GAUGE'
|
|
|
|
},
|
|
|
|
cache_rates => {
|
|
|
|
label => 'Rates hitrate',
|
|
|
|
type => 'GAUGE'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
policy_requests => {
|
|
|
|
title => 'Policy requests',
|
|
|
|
vlabel => 'Nb of policy requests',
|
|
|
|
series => {
|
|
|
|
policy_requests => {
|
|
|
|
label => 'Policy requests',
|
|
|
|
type => 'COUNTER'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
policy_timeout => {
|
|
|
|
title => 'Policy timeout',
|
|
|
|
vlabel => 'Nb of policy timeout',
|
|
|
|
series => {
|
|
|
|
policy_timeout => {
|
|
|
|
label => 'Policy timeout',
|
|
|
|
type => 'COUNTER'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
policy_matchs => {
|
|
|
|
title => 'Policy matchs',
|
|
|
|
vlabel => 'Matchs percentage'
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
my $PLUGIN_NAME = 'postfwd2';
|
|
|
|
my $CACHEFILE="$Munin::Plugin::pluginstatedir/postfwd2.cache";
|
|
|
|
|
|
|
|
my ($include, $exclude) = ($ENV{include}, $ENV{exclude});
|
|
|
|
if (defined($include) && (!defined($exclude))) {
|
|
|
|
$exclude = '.*';
|
|
|
|
}
|
|
|
|
|
|
|
|
##### Cache file, to continue to graph old policies which doesn't exist anymore
|
|
|
|
if (!(-f $CACHEFILE) || !(-e $CACHEFILE)) {
|
|
|
|
open (FILE, ">", $CACHEFILE) or munin_exit_fail();
|
|
|
|
close(FILE);
|
|
|
|
}
|
|
|
|
open (FILE, "<", $CACHEFILE) or munin_exit_fail();
|
|
|
|
my @policies = <FILE>;
|
|
|
|
close(FILE);
|
|
|
|
my %policies = map { $_, 1 } @policies;
|
|
|
|
foreach my $policy (keys %policies) {
|
|
|
|
chomp $policy;
|
|
|
|
$graphs{policy_matchs}->{series}->{$policy}->{type} = 'GAUGE';
|
|
|
|
$graphs{policy_matchs}->{series}->{$policy}->{label} = $policy;
|
|
|
|
$graphs{policy_matchs}->{series}->{$policy}->{value} = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
##### Check postfwd2 path
|
|
|
|
if (!defined($ENV{path}) || !(-x $ENV{path})) {
|
|
|
|
foreach my $path (qw{/bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin}) {
|
|
|
|
$ENV{path} = $path.'/postfwd2' if (!defined($ENV{path}) && -x $path.'/postfwd2');
|
|
|
|
last if (defined($ENV{path}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
munin_exit_fail() unless (defined($ENV{path}) && -x $ENV{path});
|
|
|
|
|
|
|
|
##### I have to parse the output BEFORE config, since policy matchs are dependant of the postfwd --dumpstats output
|
|
|
|
open(DATA, $ENV{path}.' --dumpstats |') or munin_exit_fail();
|
|
|
|
my $total_requests;
|
|
|
|
while(defined (my $data = <DATA>)) {
|
|
|
|
if ($data =~ m/^\[STATS\] postfwd2::cache .*: (\d+) queries since/) {
|
|
|
|
$graphs{cache_queries}->{series}->{cache_queries}->{value} = $1;
|
|
|
|
}
|
|
|
|
if ($data =~ m/^\[STATS\] Hitrates: ([\.\d]+)% requests, ([\.\d]+)% dns, ([\.\d]+)% rates$/) {
|
|
|
|
$graphs{cache_stats}->{series}->{cache_requests}->{value} = $1;
|
|
|
|
$graphs{cache_stats}->{series}->{cache_dns}->{value} = $2;
|
|
|
|
$graphs{cache_stats}->{series}->{cache_rates}->{value} = $3;
|
|
|
|
}
|
|
|
|
if ($data =~ m/^\[STATS\] postfwd2::policy .*: (\d+) requests since/) {
|
|
|
|
$graphs{policy_requests}->{series}->{policy_requests}->{value} = $1;
|
|
|
|
$total_requests = $1;
|
|
|
|
}
|
|
|
|
if ($data =~ m/^\[STATS\] Timeouts: .*% \((\d+) of \d+ dns queries\)$/) {
|
|
|
|
$graphs{policy_timeout}->{series}->{policy_timeout}->{value} = $1;
|
|
|
|
}
|
|
|
|
if ($data =~ m/^\[STATS\] +(\d+) matches for id: (.*)$/) {
|
|
|
|
my ($value, $label) = ($1, $2);
|
|
|
|
if ( ( !defined($exclude) ) || ( $label !~ m/$exclude/ || ( defined($include) && $label =~ m/$include/ ) ) ) {
|
|
|
|
if (!defined($policies{$label})) {
|
|
|
|
open (FILE, ">>", $CACHEFILE) or munin_exit_fail();
|
|
|
|
print FILE $label, "\n";
|
|
|
|
close(FILE);
|
|
|
|
$graphs{policy_matchs}->{series}->{$label}->{type} = 'GAUGE';
|
|
|
|
$graphs{policy_matchs}->{series}->{$label}->{label} = $label;
|
|
|
|
}
|
|
|
|
$graphs{policy_matchs}->{series}->{$label}->{value} = sprintf("%.2f", 100*$value/$total_requests);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close(DATA);
|
|
|
|
|
|
|
|
##### config
|
|
|
|
if( (defined $ARGV[0]) && ($ARGV[0] eq 'config') ) {
|
|
|
|
foreach my $key (@keys) {
|
|
|
|
print 'multigraph postfwd2_', $key, "\n";
|
|
|
|
print 'graph_title Postfwd2 ', $graphs{$key}->{title}, "\n";
|
|
|
|
print 'graph_vlabel ', $graphs{$key}->{vlabel}, "\n";
|
|
|
|
my $args = ($key eq 'cache_stats') ? ' --upper-limit 100 --rigid' : '';
|
|
|
|
print 'graph_args --lower-limit 0', $args, "\n";
|
|
|
|
print 'graph_category mail', "\n";
|
|
|
|
if ($key eq 'policy_matchs') {
|
|
|
|
print 'graph_width 600', "\n";
|
|
|
|
my @pol_keys = sort { $graphs{$key}->{series}->{$b}->{value} <=> $graphs{$key}->{series}->{$a}->{value} } keys %{$graphs{$key}->{series}};
|
|
|
|
foreach my $label (@pol_keys) {
|
|
|
|
print $label, '.label ', $graphs{$key}->{series}->{$label}->{label}, "\n";
|
|
|
|
print $label, '.draw LINE', "\n";
|
|
|
|
print $label, '.type ', $graphs{$key}->{series}->{$label}->{type}, "\n";
|
|
|
|
}
|
|
|
|
foreach my $label (@pol_keys) {
|
|
|
|
print 'multigraph postfwd2_', $key, '.', $label, "\n";
|
|
|
|
print 'graph_title Postfwd2 ', $label, "\n";
|
|
|
|
print 'graph_vlabel ', $graphs{$key}->{vlabel}, "\n";
|
|
|
|
print 'graph_width 600', "\n";
|
|
|
|
print 'graph_args --lower-limit 0 ', $args, "\n";
|
|
|
|
print 'graph_category others', "\n";
|
|
|
|
print $label, '.label ', $graphs{$key}->{series}->{$label}->{label}, "\n";
|
|
|
|
print $label, '.draw LINE', "\n";
|
|
|
|
print $label, '.type GAUGE', "\n";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach my $label (keys %{$graphs{$key}->{series}}) {
|
|
|
|
print $label, '.label ', $graphs{$key}->{series}->{$label}->{label}, "\n";
|
|
|
|
print $label, '.draw AREASTACK', "\n";
|
|
|
|
print $label, '.type ', $graphs{$key}->{series}->{$label}->{type}, "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
munin_exit_done();
|
|
|
|
}
|
|
|
|
|
|
|
|
##### fetch
|
|
|
|
foreach my $key (@keys) {
|
|
|
|
print 'multigraph postfwd2_', $key, "\n";
|
|
|
|
if ($key eq 'policy_matchs') {
|
|
|
|
my @pol_keys = sort { $graphs{$key}->{series}->{$b}->{value} <=> $graphs{$key}->{series}->{$a}->{value} } keys %{$graphs{$key}->{series}};
|
|
|
|
foreach my $label (@pol_keys) {
|
|
|
|
print $label, '.value ', $graphs{$key}->{series}->{$label}->{value}, "\n";
|
|
|
|
}
|
|
|
|
foreach my $label (@pol_keys) {
|
|
|
|
print 'multigraph postfwd2_', $key, '.', $label, "\n";
|
|
|
|
print $label, '.value ', $graphs{$key}->{series}->{$label}->{value}, "\n";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach my $label (keys %{$graphs{$key}->{series}}) {
|
|
|
|
print $label, '.value ', $graphs{$key}->{series}->{$label}->{value}, "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
munin_exit_done();
|
|
|
|
|
|
|
|
#
|
|
|
|
##
|
|
|
|
### INTERNALS FONCTIONS
|
|
|
|
###############################################################################
|
|
|
|
sub munin_exit_done {
|
|
|
|
munin_exit(0);
|
|
|
|
} ## sub munin_exit_done
|
|
|
|
|
|
|
|
sub munin_exit_fail {
|
|
|
|
munin_exit(1);
|
|
|
|
} ## sub munin_exit_fail
|
|
|
|
|
|
|
|
sub munin_exit {
|
|
|
|
my $exitcode = shift;
|
|
|
|
exit($exitcode) if(defined $exitcode);
|
|
|
|
exit(1);
|
|
|
|
} ## sub munin_exit
|